Search code examples
coopencapsulationinformation-hidingopaque-pointers

In this case, how to modularize program as well as achieving information hiding?


I created two classes "DEVICE_s" and "DEVICE_SET_s" as following:

Device_Manager.h

typedef struct DEVICE_s DEVICE_s;
typedef struct DEVICE_SET_s DEVICE_SET_s;

Device_Manager.c

struct DEVICE_s
{
    uint32_t IP;
    TYPE_e Type;
    METHOD_e Method;
    GROUP_RULE_e GroupRule;
    char Name[NAME_SIZE];
};
struct DEVICE_SET_s
{
    uint8_t     Total;
    uint8_t     Used;
    uint8_t     Available;
    DEVICE_s    Set[SET_SIZE];
};
DEVICE_s Instance;
DEVICE_SET_s Objects;

Because I put these two classes within a same file, all functions that manipulate variables "Instance" and "Objects" are put together inside this file.

I think this way is bad considering to modularity, so I want to create another source file to separately manage class "DEVICE_SET_s", just like:

DeviceSet_Manager.h

typedef struct DEVICE_SET_s DEVICE_SET_s;

DeviceSet_Manager.c

#include "Device_Manager.h"
#include "DeviceSet_Manager.h"
struct DEVICE_SET_s
{
    uint8_t     Total;
    uint8_t     Used;
    uint8_t     Available;
    DEVICE_s    Set[SET_SIZE];    //Oops! Incomplete Type Is Not Allowed
};

However, In terms of DeviceSet_Manager.c, class "DEVICE_s" is not visible(not a complete type).

How do I fix this? Thanks


Solution

  • What you want are opaque types for

    • DEVICE
    • DEVICE_SET

    This is straight forward the same way for both:

    • header, defining

      • incomplete type for object structure. A pointer to it is the opaque type to handle an object's instance and to be passed to its interfacing functions
      • interfacing functions' prototypes
    • implementation of

      • complete type
      • interfacing functions

    headers

    device.h

    #ifndef DEVICE_H
    #define DEVICE_H
    
    struct device;
    
    struct device * device_new(void);
    void device_delete(struct device *);
    
    #endif
    

    device_set.h:

    #ifndef DEVICE_H
    #define DEVICE_H
    
    #include "device.h"
    
    struct device_set;
    
    struct device_set * device_set_new(size_t);
    void device_set_delete(struct device_set *);
    
    int device_set_set_device(struct device_set *, size_t, struct device *);
    struct device * device_set_get_device(struct device_set *, size_t); 
    
    
    #endif
    

    implementations

    device.c

    #include "device.h"
    
    struct device {
      ...
    };
    
    struct device * device_new(void)
    {
      struct device * pd = malloc(sizeof * pd);
      if (NULL != pd)
      {
        /* Init members here. */
      }
    
      return pd;
    }
    
    void device_delete(struct device * pd)
    {
      if (pd)
      {
        /* de-init (free?) members here. */
      }
    
      free(pd);
    }
    

    device_set.c:

    #include "device_set.h"
    
    struct device_set
    {
      size_t total;
      size_t used;
      size_t available; /* what is this for? isn't it just total - used? */
      struct device ** pd;
    }
    
    struct device_set * device_set_new(size_t nb)
    {
      struct device_set pds = malloc(sizeof *pds);
      if (NULL != pds)
      {
        pds->pd = malloc(nb * sizeof *pds->pd);
        if (NULL == pds->pd)
        {
          free(pds);
          pds = NULL;
        }
        else
        {
          for (size_t d = 0; d < nb; ++d)
          {
            pds->pd[d] = NULL;
          }
    
          pds->total = nb;
          pds->used = 0;
          pds->available = 0;
        }
      }
    
      return pds;
    }
    
    void device_set_delete(struct device_set * pds)
    {
      if (pds)
      {
        free(pds->pd);
        free(pds)
      }
    
      return;
    }
    
    int device_set_set_device(struct device_set * pds, size_t d, struct device * pd)
    {
      int result = 0;
    
      if (pds->total <= d)      
      {
        result = ERANGE;
      }
      else
      {
        pds->pd[d] = pd;
      }
    
      return;
    }    
    
    struct device * device_set_get_device(struct device_set * pds, size_t d); 
      int result = 0;
      struct device * pd = NULL;
    
      if (pds->total <= d)      
      {
        result = ERANGE;
      }
      else
      {
        pd = pds->pd[d];
      }
    
      return pd;
    }