Убедитесь, что плохие шаблоны не возвращаются после рефакторинга - PullRequest
1 голос
/ 01 июля 2011

Я рефакторинг старого кода C. В коде абсолютно нет многоуровневой архитектуры (все доступно всем), и я пытаюсь это изменить.

Я хотел бы сократить прямой доступ к элементам структуры (по крайней мере, на данный момент написать) и разрешить доступ только через функции доступа. Есть ли какой-нибудь инструмент (или, возможно, непосредственно компилятор), который мог бы проверить это правило для меня?

Мне это нужно, так как я поддерживаю форк, и апстрим не очень заботится о качестве кода.

Ответы [ 3 ]

1 голос
/ 01 июля 2011

Лучший способ гарантировать отсутствие доступа к новым структурам кода - это не делать их доступными с помощью полной инкапсуляции.Это происходит за счет невозможности использования структуры в стеке.Вы предоставляете функцию для выделения структуры, другую для ее освобождения, и все функции модуля принимают указатель на структуру.Однако определение самой структуры находится в файле C, а не в заголовочном файле.Другим недостатком является то, что вам может потребоваться написать множество функций для управления / запроса структуры.

Я предоставлю фрагменты из старой базы кода, где я использовал этот подход.Заголовок содержит:

#ifndef INC_QUEUE_H
#define INC_QUEUE_H

typedef enum {
    QUE_OK,
    QUE_BAD_PARAM,
    QUE_NO_MEMORY,
    QUE_SYS_ERROR
} QUE_RV;

typedef struct Queue_st Queue_t;

QUE_RV QUE_New(Queue_t **ppQueue);
QUE_RV QUE_Put(Queue_t *pQueue, int priority, void *pData);
QUE_RV QUE_Get(Queue_t *pQueue, int *priority, void **ppData);
void QUE_Free(Queue_t *pQueue);

#endif /* INC_QUEUE_H */

Файл C определяет структуру Queue_st и реализации функций (сильно модифицированных для выделения подхода):

#include "queue.h"
#include "log.h"

#define QUE_INITIAL_CAPACITY 128

struct Queue_st {
    /* SNIP: structure contents go here */
};

QUE_RV QUE_New(Queue_t **ppQueue)
{
    QUE_RV rv;

    *ppQueue = malloc(sizeof(Queue_t));

    /* SNIP: Check malloc, Initialize the structure here ... */

    return QUE_OK;
}

void QUE_Free(Queue_t *pQueue)
{
    if (pQueue != NULL)
    {
        /* SNIP: Free contents of the structure before the free below... */
        free(pQueue);
    }
}

Альтернативным подходом являетсяиспользовать typedef struct StructName *StructHandle; и заменить все указатели в API на StructHandle.На один * меньше беспокоиться.


РЕДАКТИРОВАТЬ: Если вы хотите, чтобы некоторые члены были видимыми, а некоторые нет, это также возможно с расширением вышеуказанного подхода.В своем заголовке определите:

typedef struct StructPriv StructPriv;

typedef struct {
    /* public members go here */

    StructPriv *private;
} Struct;

Struct *STRUCT_Create();
void STRUCT_Free();

В файле C определите закрытые члены и функции, которые ими управляют.

0 голосов
/ 01 июля 2011

Вы можете использовать предыдущие инструменты, предложенные мной, или это только для C ++ и opensource. Vera ++

Вы можете написать свое собственное правило, используя Tcl.

0 голосов
/ 01 июля 2011

Я думаю, вы можете использовать checkstyle или PMD с IDE затмения.В обеих утилитах вы можете настроить свои собственные правила.

...