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 the entity as unique as possible, and so much so that it can be easily found with any text editor. To date, IDE support excellent thing - «the Find Usages of» (search uses) , but it does not always help, and I will write about it below.

    Naming in the style of Hungarian notation I did not like. I have not liked this approach since C ++ / Delphi - I considered it redundant and not always clear. I liked the implementation of BEMbut to the full I don’t use it either. I tried to isolate and combine the methods that I liked most, and I will tell you about them.






    CSS


    I start all CSS classes with the prefix “cl_”, identifiers with the prefix “id_”. If the class or identifier belongs to the block, I add after the prefix “b_”, if to the module - “m_”. I also indicate 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. And to find such names is much easier if you need, for example, to refactor and see where it can be reflected.

    By the way, such code is easier to drive through compression and obfuscation . Moreover, no analyzers are needed - look for regulars by prefixes and compress. Actually, that's why different prefixes are used for identifiers and classes. I think the article about compression and obfuscation will be interesting to the Habr audience, I’ll try to arrange it as time appears.




    PHP (Yii)


    It’s somehow wrong that controllers, validators, etc. have additional prefixes and postfixes, but models do not. I decided that because of the “magic” of Yii, it would be hard to find where the User class is used, and with a simple text search, the word User would be found wherever possible.

    Therefore, model classes are referred to as WbUserModel, WbCatalogItemModel, etc., where:
    • Wb: project identifier (short for name);
    • User: actually, the model;
    • Model: means that it is a model and not something else.


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

    The use of such names gives uniqueness, and in which case I can even find all uses of a particular class even without an IDE. I’m also trying in every possible way to abandon the use of the textual representation of classes and attributes, I especially consider it a big evil when a link to a class is generated from the union of strings - this cannot be found either through “Find Usages” or through a search in the text. For example:

    publicfunctionactionGetData($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, at a glance it is immediately clear that this is not an attribute of the model, but rather a connection with another model. Although according to the Yii concept this is presented as one and the same (attribute of the model), I still think that these are different things. Besides adding a prefix, I always add the model class name as well. Yes, this approach may be less beautiful, but dry and specific - when I look at the code, I immediately understand what it depends on and where the data came from.

    publicfunctionrelations(){
        returnarray(
            'R_PriceItems' => array(self::HAS_MANY, WbCatalogPriceItemModel::CLASS, 'category_id'),
            'R_CategoryParent' => array(self::BELONGS_TO, WbCatalogCategoryModel::CLASS, array('parent_id' => 'id'),
        )
    }
    publicfunctionRecalculatePriceItems(){
        foreach ($this->R_PriceItems as $price_item) {
            $price_item->price = $price_item->new_price;
        }
    }
    


    As you can see in the code above (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 replace _CLASS_ () with CLASS with a simple “Find And Replace” without any problems.

    classActiveRecordextendsCActiveRecord{
        publicstaticfunction_CLASS_(){
            return get_called_class();
        }
    }
    





    “FOR” or “AGAINST”


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

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

    Against such a naming scheme, one can cite the fact that this information is redundant, and (as it were) it is not worth littering the code with prefixes and postfixes. In addition, it is necessary to teach other (and new) employees to understand how and what to name (although personally I do not see this as a problem).

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

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




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

    Only registered users can participate in the survey. Please come in.

    Should I use prefixes and postfixes?


    Also popular now: