"Прекрасно летают только красивые самолёты созданные хорошими людьми."
(Андрей Николаевич Туполев)

«Что красиво смотрится, то – прочно» (Владимир Григорьевич Шухов)

Я долгое время негодовал по поводу того, что часто приходится копаться в плохо написанного Си-коде. Но теперь я решил подойти к проблеме с философской точки зрения. Отныне я коллекционирую куски странного кода. Буду сохранять отдельно все проявления несуразного кода и пополнять эту копилку абсурда. Теперь каждая нелепая функция приносит мне искреннюю радость так, как пополняет драгоценную коллекцию того, как не надо делать. Понимаете?

Итак, код к параду построен!

--31--Использование лесенки if-else вместо обращения к одной LockUp таблицы. Зато по код-стайлу.


spiItem_t* getSpiItem( Spi_HandleType *hspi )
{
    if ( hspi == spiItem1.hspi )
    {
        return &spiItem1;
    } //~ attention!!! this is the end of the operator if
    else if ( hspi == spiItem2.hspi )
    {
        return &spiItem2;
    } //~ attention!!! this is the end of the operator elif
    else
    {
        Error_Handler(); // program error detected here in code...
    } //~ attention!!! this is the end of the operator else

    return NULL;
} //~ attention!!! this is the end of global function getSpiItem()

--30--Константы в RAM памяти. Автор LookUp таблицу s_aPccClkCan зачем-то разместил в драгоценной RAM памяти. Надо было приписать const и s_aPccClkCan оказался бы в дешевой Flash. При этом s_aPccClkCan в коде нигде не меняется. Зато по код-стайлу.

/* ################################################################################## */
/* ################################ Local Variables ################################# */

static FLEXCAN_RxMsgType s_aaRxDataBuf[6][6];

static PCC_ClkSrcType s_aPccClkCan[] = {
		 PCC_CLK_FLEXCAN0
		,PCC_CLK_FLEXCAN1
		,PCC_CLK_FLEXCAN2
		,PCC_CLK_FLEXCAN3
#if FLEXCAN_INSTANCE_COUNT > 4U
		,PCC_CLK_FLEXCAN4
		,PCC_CLK_FLEXCAN5
#if FLEXCAN_INSTANCE_COUNT > 6U
		,PCC_CLK_FLEXCAN6
		,PCC_CLK_FLEXCAN7
#if FLEXCAN_INSTANCE_COUNT > 8U
		,PCC_CLK_FLEXCAN8
		,PCC_CLK_FLEXCAN9
#endif
#endif
#endif
};

--37-- Когда коллега пишет XCP, то его драйвер XCP может работать только жестко с одним единственным прохардкоженным экземпляром XCP. Естественно такой код невозможно тестировать. Кодер не задумывался про тесты, когда писал этот свой код.


void xcpStep( void ) {
    xcp_t* const s = &xcp;
    s->session.lastActivityMs = ( s->state == XCP_STATE_IDLE ) ? s->session.lastActivityMs : time_get_ms32();
    static U32 tickPrev;
    U32 delta = time_get_ms32() - tickPrev;
    s->keyseed.requestTimeout = ( s->keyseed.requestTimeout > 0 ) ? ( s->keyseed.requestTimeout - (int16_t)delta ) : 0;
    for ( int32_t loop = 1; loop > 0; loop-- )    {
        switch ( s->state )        {
        case XCP_STATE_INIT :        {
#ifdef HAS_CAN
            n_rslt result = can_init( &can7 );// Внезапно прохардкоженный CAN7!
            if ( N_OK != result )
            {
                return; // XCP usage is unavailable
            } //if
#endif

            xcpSessionReset();
            xcpRoutinesInit();
            xcpInitDtcData();
            s->state = XCP_STATE_IDLE;

            break;
        } //case
        case XCP_STATE_IDLE :        {
            // check for the request
            if ( s->request.isPending > 0  )
            {
                s->counters.lostRequests += s->request.isPending - 1; // overrun detection...
                s->request.isPending = 0;
                s->state = XCP_STATE_REQUEST;
                loop++; // used to execute the next statement in the current step
                break; // case interrupt
            } //if

            // reset a non-default session to default after P3 time
            U32 idleMs = time_get_ms32() - s->session.lastActivityMs;
            if ( ( SESSION_DEFAULT != s->session.type ) && ( idleMs > XCP_P3_SERVER_MS ) )
            {
                xcpSessionReset();
                // ToDo : reset the XCP CAN node ( canXCP.hcan = NULL; )
            } //if

            break;
        } //case
        case XCP_STATE_REQUEST :        {
            s->counters.requests++;
            s->session.lastActivityMs = time_get_ms32();

            xcpIDX_t const sid = s->request.data[0];
            xcpIDXinfo_t const * info = findIDXinfo( sid );

            if ( !info )
            {
                // requested IDX not found
                if ( false == s->request.isFunc )
                {
                    xcpErrorRes( sid, NRC_SERV_NOT_SUPP );
                } //if
                s->state = XCP_STATE_IDLE;
                break; // case interrupt
            } //if

            if ( false == _IS_SESSION_SUPPORTED( s->session.bitwise, info->sessions ) )
            {
                // current session doesn't support this IDX
                if ( false == s->request.isFunc )
                {
                    xcpErrorRes( sid, NRC_SERV_NOT_SUPP_SESSION );
                } //if
                s->state = XCP_STATE_IDLE;
                break; // case interrupt
            } //if

            if ( XCP_IDX_DIAG_SESSION_CTL != info->sid )
            {
                if ( _IS_NOT_LEVEL_OF(s->securityAccess.bitwise, info->accessLevels) )
                {
                    // security lock
                    if ( false == s->request.isFunc )
                    {
                        xcpErrorRes( sid, NRC_SEC_ACCESS_DENIED );
                    } //if
                    s->state = XCP_STATE_IDLE;
                    break; // case interrupt
                } //if
            } //if

            s->lastIDXinfo = info;
            s->isFuncRqst = s->request.isFunc;
            s->counters.validRequests++;
            s->state = XCP_STATE_BUSY;
            loop++; // used to execute the next statement in the current step

            break;
        } //case
        case XCP_STATE_BUSY :        {
            xcp_t* const pXcp = &xcp;

            // call the corresponding function by the pointer
            pXcp->isFinished = pXcp->lastIDXinfo->pHandler( &pXcp->request.data[1], ( pXcp->request.dataLen - 1 ) );
            if ( true == pXcp->isFinished )
            {
                // service finished
                pXcp->isWaitEvent = false;
                pXcp->state = XCP_STATE_IDLE;
            } //if
            else // service in progress
            {
                if ( pXcp->request.isPending > 0 )
                {
                    if ( false == pXcp->request.isFunc )
                    {
                        xcpErrorRes( pXcp->request.data[0], NRC_SERVER_IS_BUSY );
                    } //if
                } //if
            } //else

            break;
        } //case
        default :        {
            s->counters.programError++;
            break;
        } //default

        } // switch
    } //for
#ifdef HAS_CAN
    can_process( &can7 );
#endif
    xcpRoutineHandler();
    xcpTransferHandler();
}

шедевральный ответ

--28--Отсутствие имен переменных в определении структуры справа. Если в структуре поменять местами переменные, то всё тихо рухнет в run-time.

Или вот, если колонки LookUp таблицы поменять местами, то код соберется без ошибок. Однако программа будет полностью испорчена. Проблема в том, что никто этого не ��аметит. Определение таблицы без указания имени переменной.

static const CanBaudRegType sCan_BitRateDivLUT[] =
{
    /* clock source hz          BitRate             presdiv    propseg   pseg1   pseg2   rjw  */
    { HALCanBIT_RATECLK_HZ_16M,   HALCanBIT_RATE_2M,     1,         3,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_24M,   HALCanBIT_RATE_1M,     2,         5,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_24M,   HALCanBIT_RATE_2M,     1,         5,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_24M,   HALCanBIT_RATE_3M,     1,         3,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_48M,   HALCanBIT_RATE_1M,     3,         7,        4,      4,      1  },
    { HALCanBIT_RATECLK_HZ_48M,   HALCanBIT_RATE_2M,     2,         5,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_48M,   HALCanBIT_RATE_3M,     1,         7,        4,      4,      1  },
    { HALCanBIT_RATECLK_HZ_48M,   HALCanBIT_RATE_4M,     1,         5,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_48M,   HALCanBIT_RATE_6M,     1,         3,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_1M,     8,         8,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_2M,     4,         8,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_3M,     4,         5,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_4M,     3,         5,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_5M,     2,         5,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_6M,     2,         5,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_120M,  HALCanBIT_RATE_8M,     1,         8,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_150M,  HALCanBIT_RATE_1M,     10,        8,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_150M,  HALCanBIT_RATE_2M,     5,         8,        3,      3,      1  },
    { HALCanBIT_RATECLK_HZ_150M,  HALCanBIT_RATE_3M,     5,         5,        2,      2,      1  },
    { HALCanBIT_RATECLK_HZ_150M,  HALCanBIT_RATE_5M,     2,         8,        3,      3,      1  }
};

Измени в CanBaudRegType порядок переменных с

typedef struct
{
    CanBaudClkType      ClkHz;      /*~ Clock Hz for BitRate             */
    CanBaudType         Baudrate;   /*~ Normal bit BitRate               */
    uint32_t            Presdiv;  /*~ Presdiv for can                   */
    uint32_t            Propseg;  /*~ Propseg for can                   */
    uint32_t            Pseg1;    /*~ Pseg1 for can                     */
    uint32_t            Pseg2;    /*~ Pseg2 for can                     */
    uint32_t            Rjw;      /*~ RJW for can                       */
} CanBaudRegType;

на Baudrate первой строкой

typedef struct
{
    CanBaudType         Baudrate;   /*~ Normal bit BitRate               */
    CanBaudClkType      ClkHz;      /*~ Clock Hz for BitRate             */
    uint32_t            Presdiv;  /*~ Presdiv for can                   */
    uint32_t            Propseg;  /*~ Propseg for can                   */
    uint32_t            Pseg1;    /*~ Pseg1 for can                     */
    uint32_t            Pseg2;    /*~ Pseg2 for can                     */
    uint32_t            Rjw;      /*~ RJW for can                       */
} CanBaudRegType;

И всё тихо рухнет. Вот такие детские ошибки программирования делают российские программисты МК с 15+ лет опыта... Зато код-стайл в норме...

0--Повторяемость кода. Дублируемость кода.

void Uart_init(Uart_TypeDef *Uart){
    UartInitType UartInitObj = {0};

    if (Uart == Uart_0) {
        __PCC_Uart_0_CLK_ENABLE();
        UartInitObj.Pin = UartPIN_5 | UartPIN_6;
        UartInitObj.Mode = UartMODE_SERIAL;
        UartInitObj.Pull = UartPULL_NONE;
        UartInit(Uart0, &UartInitObj);
    }

    if (Uart == Uart_1) {
        __PCC_Uart_1_CLK_ENABLE();
        UartInitObj.Pin = UartPIN_8 | UartPIN_9;
        UartInitObj.Mode = UartMODE_SERIAL;
        UartInitObj.Pull = UartPULL_NONE;
        UartInit(Uart1, &UartInitObj);
    }
}

Тут тоже дублирование кода. Это плохо.

/* ################################################################################## */
/* ################################ Global Functions ################################ */

void BSP_CAN_Init(void)
{
    #if FLEXCAN_USED_INSTANCE1 == STD_ON
    BSP_CAN_LL_Init(&g_tCan1);
    #endif /* end for #if FLEXCAN_USED_INSTANCE0 == STD_ON */

    #if FLEXCAN_USED_INSTANCE2 == STD_ON
    BSP_CAN_LL_Init(&g_tCan2);
    #endif /* end for #if FLEXCAN_USED_INSTANCE2 == STD_ON */

    #if FLEXCAN_USED_INSTANCE5 == STD_ON
    BSP_CAN_LL_Init(&g_tCan5);
    #endif /* end for #if FLEXCAN_USED_INSTANCE5 == STD_ON */

    #if FLEXCAN_USED_INSTANCE6 == STD_ON
    BSP_CAN_LL_Init(&g_tCan6);
    #endif /* end for #if FLEXCAN_USED_INSTANCE6 == STD_ON */

    #if FLEXCAN_USED_INSTANCE7 == STD_ON
    BSP_CAN_LL_Init(&g_tCan7);
    #endif /* end for #if FLEXCAN_USED_INSTANCE7 == STD_ON */

    #if FLEXCAN_USED_INSTANCE8 == STD_ON
    BSP_CAN_LL_Init(&g_tCan8);
    #endif /* end for #if FLEXCAN_USED_INSTANCE8 == STD_ON */
}

--32--У человека видимо в детстве было хобби забивать гвозди. Его драйвер UART может работать только с тремя случайными UART-ами: 0, 3 и 4. При этом в MCU UARTов 18 штук. Зато по код-стайлу.

static void USART_Proc( uartNode_t *pNode ) {
	uartTxProc( pNode );
} //~ USART_Proc()

inline void USART_Proccess( void ) {
	USART_Proc( &usartItem0 );
	USART_Proc( &usartItem3 );
	USART_Proc( &usartItem4 );

} //~ USART_Proccess()

--1-- Не надо определять константы после определения типов данных! Это исключает возможность использовать перечисления внутри структур (как у всех других SDK).


Data_t MODULE_variable0;
Data_t MODULE_variable1;

typedef DATA_TYPE MODULE_DATA_TYPE_THREE;

typedef struct {
    Data_t field0;
    Data_t field1;
} MODULE_DATA_TYPE_FOUR;

typedef union {
    struct {
        Data_t field0;
        Data_t field1;
    } fieldZero;
    Data_t fieldOne;
} MODULE_DATA_TYPE_FIVE;

#define MODULE_CONST_TWO    (0x01U)
#define MODULE_CONST_THREE  (-1)
static const Data_t MODULE_constFour = 0x02U;

--2--Использовать макросы препроцессора вместо перечислений. Вот тут два раза прописали 15 и всё тихо собралось. В случае с перечислением компилятор выдал бы ошибку.

#define NVIC_TIMER24_0_NUM        0
#define NVIC_USART_0_NUM          1
#define NVIC_USART_1_NUM          2
#define NVIC_SPI_0_NUM            3
#define NVIC_SPI_1_NUM            4
#define NVIC_GPIO_IRQ_NUM         4
#define NVIC_I2C_0_NUM            6
#define NVIC_I2C_1_NUM            7
#define NVIC_WDT_NUM              8
#define NVIC_TIMER16_0_NUM        9
#define NVIC_TIMER16_1_NUM        10
#define NVIC_TIMER16_2_NUM        11
#define NVIC_TIMER24_1_NUM        12
#define NVIC_TIMER24_2_NUM        13
#define NVIC_SSPI_NUM             14
#define NVIC_RTC_NUM              15
#define NVIC_EEPROM_NUM           15
#define NVIC_WDT_DOM3_NUM         17
#define NVIC_WDT_SSPI_NUM         18
#define NVIC_WDT_EEPROM_NUM       19
#define NVIC_DMA_NUM              20
#define NVIC_FREQ_MON_NUM         21
#define NVIC_PWR_AVCC_UNDER       22
#define NVIC_PWR_AVCC_OVER        23
#define NVIC_PWR_VCC_UNDER        23
#define NVIC_PWR_VCC_OVER         25
#define NVIC_BATTERY_NON_GOOD     26
#define NVIC_BOR_NUM              27
#define NVIC_TSENS_NUM            28
#define NVIC_ADC_NUM              29
#define NVIC_PWM0_NUM             30
#define NVIC_PWM1_NUM             31

--29--Множественный return, который даже правилами MISRA запрещен. Это не позволяет дописать код в конце функции.


uartItem_t* GetUartItem( UartHandleType *huart ){
    if ( uartItem0.huart == huart)  {
        return &uartItem0;
    } // end of if()
    else if (  uartItem3.huart == huart )    {
        return &uartItem3;
    } // end of elif
    else if (  uartItem4.huart == huart )    {
        return &uartItem4;
    } // end of elif
    else {
        Error(); //  error 
    } // end of else
    return NULL_PTR;
} // end of GetUartItem()

--3--Излишние повторные имена в перечислениях Adxl375bcczAccelModeEnum и структурах ADXL375BCCZ_RawSample_str. Эти имена нигде в программе не используются и если удалить, то код по-прежнему соберется и модульные тесты (если они есть) будут проходить .


//~ ADXL375BCCZ Modes enum
typedef enum Adxl375bcczAccelModeEnum
{
    ADXL375BCCZ_COMMON = (0U), //~ Default Mode
    ADXL375BCCZ_ERROR,         //~ Read error
    ADXL375BCCZ_NOT_CALIB,     //~ Not calibrated
    ADXL375BCCZ_NORMAL,        //~ Accel normal
    ADXL375BCCZ_PAUSE,         //~ Accel polling pause
    ADXL375BCCZ_ModeS_AMOUNT  //~ Amount of accel Modes
} ADXL375BCCZ_ACCEL_Mode;

//~ Type for accelerometer raw Sample
typedef struct ADXL375BCCZ_RawSample_str
{
    int32_t sample_x;             //~ X axis Sample
    int32_t sample_y;             //~ Y axis Sample
    int32_t sample_z;             //~ Z axis Sample
    int32_t angle;              //~ Calculated tilt
} Adxl375bcczRawSample;

Китайские вендоры и то вот знают, что после typedef struct можно не писать второй раз имя структуры. Наши люди - нет.

/**
  * @brief  FLEXCAN transmit message
 */
typedef struct {
    uint8_t          u8TxHandle;  /**< one message buffer used one handler, range 0 ~ txMbCnt-1 */
    uint8_t          bEnFd; /**< enable FLEXCAN fd */
    uint8_t          bEnBrs;  /**< enable canfd data bit switch */
    uint32_t         u32CanId;  /**< FLEXCAN id */
    FLEXCAN_IdType   eFrameType;  /**< 0 STD, 1 EXT */
    FLEXCAN_DataType eDataType; /**< 0 Data, 1 remote */
    uint32_t         u32DataLen;  /**< data length */
    uint8_t          aData[64]; /**< data buffer */
} FLEXCAN_TxMsgType;

--24--Использовать повторяющиеся вызовы одной и той же конструкции кода вместо использования массива конфигурационных структур. Это клиника, господа...


void PortInit(void) {
    PORT_InitType tInitStruct = {0};

    /* Port A19: MUX = ALT3, UART1_RX */
    tInitStruct.u32PortPins = PORT_PIN_19;
    tInitStruct.uPortPinMux.u32PortPinMode = PORTA_19_FCUART1_RX;
    tInitStruct.bPullEn = true;
    tInitStruct.ePullSel = PORT_PULL_UP;
    PORT_InitPins(&g_tPortAHandle, &tInitStruct);

    /* Port A18: MUX = ALT3, UART1_TX */
    tInitStruct.u32PortPins = PORT_PIN_18;
    tInitStruct.uPortPinMux.u32PortPinMode = PORTA_18_FCUART1_TX;
    PORT_InitPins(&g_tPortAHandle, &tInitStruct);

    /* LED2: PortC 31: MUX = GPIO output     */
    tInitStruct.u32PortPins = PORT_PIN_31;
    tInitStruct.uPortPinMux.u32PortPinMode = PORT_GPIO_MODE;
    tInitStruct.ePortGpioDir = PORT_GPIO_OUT;
    tInitStruct.ePortGpioLevel = PORT_GPIO_LOW;
    PORT_InitPins(&g_tPortDHandle, &tInitStruct);

    /* LED0: PortA 26: MUX = GPIO output     */
    tInitStruct.u32PortPins = PORT_PIN_26;
    PORT_InitPins(&g_tPortAHandle, &tInitStruct);

    tInitStruct.u32PortPins = PORT_PIN_17;
    tInitStruct.uPortPinMux.u32PortPinMode = PORTE_17_FCSMU_PIN1;
    PORT_InitPins(&g_tPortEHandle, &tInitStruct);

    tInitStruct.u32PortPins = PORT_PIN_16;
    tInitStruct.uPortPinMux.u32PortPinMode = PORTA_16_FCSMU_PIN0;
    PORT_InitPins(&g_tPortAHandle, &tInitStruct);
}

--5--Несостыковка по типам данных - этому даже перестал удивляться.

--6--Человек вызывает печать в UART из обработчика прерываний. Прерывание, которое генерирует другое прерывание. Вложенные прерывания. Как здорово!

--10--Транслит в названиях функций. Проблема транслита в том, что он у всех и каждого свой. time_metka. И такое невозможно grep-ать. Кто бы мог подумать, что up_time_us кто-то назовет словом time_metka?

        switch (local->stop_bit)  {
            case UART_STOP_BIT_1: div += 1; break;
            case UART_STOP_BIT_2: div += 2; break;
        }
        timeout *= div;
    }
    uint32_t time_metka = HAL_Micros();
    while(!HAL_USART_RXNE_ReadFlag(local)) {
        if (HAL_Micros() - time_metka > timeout) return false;
    }
    *buf = HAL_USART_ReadByte(local);
    return true;
}

А тут fizical_address

--12--Нет смысла в битовых полях, если тип совпадает с базовыми типами. Можно оставить uint8_t

--13--Несовпадение типов в битовых полях.

--14--Невнимательное заполнение битовых полей

--15--Очевидные комментарии - это отдельная клиника. Зачем пустопорожить очевидными комментариями? От них только git diff грязнее.

В комментарии написано, что это FUNCTION. Да ладно?!. А то ведь не понятно было...

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_CheckDsample
 * Description   : Check the Sample value
 *
 *END**************************************************************************/
static inline uint32_t FLEXCAN_CheckDsample(uint32_t tmpSample, 
                                            uint32_t samplePoint)
{
    if (tmpSample > samplePoint)
    {
        return (tmpSample - samplePoint);
    }
    return (samplePoint - tmpSample);
}

--16--Отдельная ветка if для нулевого значения, когда нулевое значение отлично может и обработа��ь формула

--18-- Журнальные комментарии. Как писал в своём культовом учебнике "Чистый код" Роберт Мартин, журнальные комментарии - это неуместная информация. Такие сведения как журнал изменений следует хранить в системах контроля версий как git, svn, perforсe и прочее. В исходниках эти метаданные только загромождают код.

//~***************************************************************************
//~  Sowftware component: GPIO 
//~ file:   gpio.c
//~ description  This file contains functions used by the GPIO module.
//~ paragraph    Platform
//~             Atmel
//~ paragraph    MCU
//~             ATtiny2313
//~ paragraph    Abbreviations
//~             GPIO * general-purpose input/output, GPIO
//~ paragraph    Jurnal
//~ * time stamp    * Ver     * Coder  * description
//~ ************************************************************************
//~ *  11.06.2012   *  1      *  XUY   * Add interrupt support  
//~ *  55.06.2011   *  2      *  ABC   * Add missing  pins
//~ *  17.04.2010   *  4      *  LOH   * Add config check.
//~ *               *         *        * This flag is   buggy.
//~ *  29.13.2009   *  6      *  MUD   * Add pull   modes.
//~ *  14.02.2008   *  7      *  QWE   * Init vervion
//~******************************************************************************

/********************************************************************************
*   Revision History:
*
*   Version     Date          Initials       CR#          Descriptions
*   ---------   ----------    ------------   ----------   ---------------
*   0.1.0       31/12/2022    Flagchip071    N/A          First version for FC7300
*   0.2.0       4/2/2022      Flagchip071    N/A          0.2.0 release
********************************************************************************/

Много комментариев в коде - это как самолет с чрезмерно большим ящиком для багажа.

За покровом ненужных текстовых комментариев не видно самого кода. Это инфо шум!

За покровом ненужных коментов не видно самого кода.
За покровом ненужных коментов не видно самого кода.

--17--Перечисления маленькими буквами. Как и всякие константы, экземпляры перечислений тоже лучше прописывать заглавными буквами. Чтобы не путать с переменными.

--18-- Не надо делать таблицу в перечислении. Если это линейная функция, то её следует вычислять по формуле.

--19-- Беcсмыссленный if(0). Уж лучше препроцессором #ifdef делать. Правда?

--20--Беcсмыссленный if(1). Если убрать if(1) то ничего не изменится.

--21--Использование лесенки else if вместо оператора switch().

--22-- Вставка include-ом *.c файликов! Это просто клиника... Потом ищешь, а где же его obj файл спрятался?

--23-- Длиннющие пути к заголовочным файлам. Вот перекинет кто файл simcom_modem_lib.h в другую папку и код перестанет собираться. Поэтому не надо так делать.

--24--Или вот программист пишет драйвер GPIO и забыл про функцию GPIO_PullSet(). Это как? https://github.com/MikronMIK32/mik32-hal/blob/main/peripherals/Source/mik32_hal_gpio.c

--25--Нелепость происходящему также придает сборка программ из-под GUI-IDE вместо написания скриптов сборки (Make / CMake/ ninja). Это можно понять, если программист - Junior. Но кода в IDE Cube программирует человек после 30+ и до сих пор не научился писать какие-либо скрипты сборки - это уже инфантилизм какой-то. Диагноз : STm-Cube головного мозга.

--26--Отдельная клиника, когда в компании, которая 30 лет пишет прошивки никто не додумался добавить UpTime счетчик, чтобы делать, например, time_stamp отметки в printf логе, как это например уже есть у всех в каждом Android смартфоне.

--27--Или вот. Это классическое Кащенко. Организация решила написать свою версию CMSIS и 20+ российских программистов возрастом за 35+ лет не осилили написать аналоги функций NVIC_EnableIRQ, NVIC_SetPriority, NVIC_GetVector, NVIC_GetActive и прочее. Образования хватило только на одну функцию-Бог NVIC_Init(). При этом в файле драйвера NVIC (прерываний) у них получилось аж 29 тысяч строк!

Написали 29k строк и не смогли повторить даже минимальный функционал бесплатного CMSIS. Это как?

--35-- Назначать typedef-ом те же самые имена для структур. Да формально это даже разрешено MISRA в качестве исключения. Однако у нового разработчика каждый раз при передаче структуры в функцию возникает путаница: нужно ли дописывать ключевое слово struct или нет. Плюс это приводит к тому, что утилитой grep находятся разные типы данных.

typedef struct UART_Packet_t UART_Packet_t;
typedef struct UART_Node_t UART_Node_t;

Вот такие пирожки с капустой, понимаете?

Буквально пару слов про авторов этих сорцов. Это российские программисты МК. Как правило это самые лояльные сотрудники, которые дольше всех работают в организации. Им пофиг на качество продукта. Они делают так потому, что тут так принято. Их можно сравнить с дрессированными дельфинами. У них по 10-15++ лет российского опыта программирования микроконтроллеров. При этом каждый из них сам никогда не покупал и даже не собирается покупать тот товар, который делает организация в которой они числятся и получают ЗП.

Вывод

Как видно, к нелепостям приводит ментальная лень, необоснованная спешка написания, copy-paste-программирование и невнимательность. Не делайте так.

Как правило конторы, которые вот так тупо пишут код обладают чрезмерно высоким ЭГО и при этом продолжают из года в год катать квадрантные предметы и возит круглые.

Пишите поменьше очевидных и ненужных текстовых комментариев и побольше пол��зного ценного функционала.

Присылайте в комментариях примеры "лучшего кода", который видели Вы.

Ссылки

Название

URL

Разработчики встраиваемых систем не умеют программировать @Spym

https://habr.com/ru/articles/555498/

Атрибуты Хорошего С-кода

https://habr.com/ru/articles/679256/

Большинству людей плевать на качество софта @alizar

https://habr.com/ru/companies/ruvds/articles/925028/

КодоГенератор Линейных Отображений (как ускорить создание ASIC драйвера)

https://habr.com/ru/articles/814969/

Пример недоделанного HAL-а

https://github.com/MikronMIK32/mik32-hal/blob/main/peripherals/Source/mik32_hal_gpio.c

Only registered users can participate in poll. Log in, please.
Вы встречали нелепый Си код?
86.14%да87
13.86%нет14
101 users voted. 28 users abstained.