(Logo)

Mofafen Blog

Articles

Sharing thoughts and ideas

  • Code Smells

    What is a code smell ?

    A code smell is any characteristic in the source code of a program that possibly indicates a deeper problem. These are indicators that warn you that something is wrong in the code, without showingany errors in execution.

    What are common code smells ?

    Code smells categorization

    Code smells can be categorized according to which aspect is impacted in the code base. A common categorization is : - Bloaters : - Practices that leads to increase the codebase in large proportions and make it hard to work with. - Object-Orientation Abusers: - Misapplication of object orientated paradigm - Change Preventers - Practices that prevents flexible changes in the code, meaning that doing a single change needs to be applied in several part of the code repeatably. - Dispensables - Points at parts of the source code that are unneeded, and that will make the code clearner if absent. - Couplers - Codes that excessively coupling together part of codes ( classes ).

    1. Code duplicates

    2. Principle of least knowledge

    3. Inappropirate intimacy

    4. Feature envy

    Feature Envy occurs when a class of method accesses the data of another object more than its own data.

    #include <string>
    #include <vector>
    using namespace std;
    // Request.hpp
    class Request{
    public:
       string get_some_data(){ return "A";}
       string get_some_data2(){ return "B";}
       [...] 
    };
    
    // In Config.cpp
    void process_config(const Request& iReq){
        vector<string> list_data;
        // Extract data
        list_data.emplace_back(iReq.get_some_data());
        list_data.emplace_back(iReq.get_some_data2());
        [...]
        // Process data
        /* Do some work */
    }
    

    In this example, in the config module we pull several pieces of data, but the function process_config just want to process the data. An alternative could be to provide the data directly as a parameter instead of the Request object and retrieve the data through a iReq.extract_config_data(). Another alternative, if the process only concern the Request object, would be to directly use iReq and tell it to process its own data : iReq.process_data(). This solution improves encapsulation and reduces duplication of logic.

    5. Primitive obsession

    Primitive Obsession is a code smell that arises when primitive types ( such as int, float, ...) are used to represent domain concepts instead of creating small and meaningful structures. Common examples include: - Using a float to represent a monetary value instead of a dedicated Currency type. - Representing a phone number as a string instead of a PhoneNumber object. - Passing coordinates as separate x and y values instead of a Point or Position structure.

    Example : Bad example:

    void set_pos(float x, float y){ ...}
    

    Better example, encapsulating x and y

    void set_pos(Pos pos){ ...}
    

    By introducing a small structure like Pos, we: - Improve readability and expressiveness.
    - Reduce the risk of incorrect parameter ordering. - Enable validation and behavior inside the type itself. - Prepare the code for future extension without breaking existing interfaces.

    6. Speculative generality

    7.

    Codesmell