文章 "MQL5中表格模型的实现:应用MVC概念"

 

新文章 MQL5中表格模型的实现:应用MVC概念已发布:

在本文中,我们将探讨如何使用MVC(模型-视图-控制器)架构模式在MQL5中开发表格模型,该模式可将数据逻辑、展示和控制进行分离,从而实现结构化、灵活且可扩展的代码。我们将考虑实现用于构建表格模型的各类,包括使用链表来存储数据。

对于编程而言,应用程序架构对于确保可靠性、可扩展性和易于维护起着关键作用。有助于实现这些目标的方法之一,是采用名为MVC(模型-视图-控制器)的架构模式。

MVC概念允许将应用程序划分为三个相互关联的组件:模型(负责数据和逻辑管理)、视图(负责数据展示)和控制器(负责处理用户操作)。这种分离简化了代码的开发、测试和维护,使其更加结构化和灵活。

在本文中,我们将探讨如何运用MVC原则,在MQL5语言中实现一个表格模型。表格是存储、处理和展示数据的重要工具,合理组织表格能极大地简化信息处理工作。我们将创建用于操作表格的类:包括表格单元格类、表格行类以及表格模型类。为了在表格行内存储单元格,以及在表格模型内存储行,我们将使用MQL5标准库中的链表类,这些类能够高效地存储和使用数据。


作者:Artyom Trishkin

 

你好,Artem。

我有个问题:

您的代码读取了对象类型。

      //--- 读取对象类型
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

但没有像 SB 中那样进行检查。

bool CList::Load(const int file_handle)
  {
   uint     i,num;
   CObject *node;
   bool     result=true;
//--- 检查
   if(file_handle==INVALID_HANDLE)
      return(false);
//--- 读取并检查开始标记 - 0xFFFFFFFFFFFFFFFFFFFFF
   if(FileReadLong(file_handle)!=-1)
      return(false);
//---读取和检查类型
   if(FileReadInteger(file_handle,INT_VALUE)!=Type())
      return(false);
//--- 读取列表大小
   num=FileReadInteger(file_handle,INT_VALUE);
//-- 使用调用方法 Load() 顺序创建列表项
   Clear();
   for(i=0;i<num;i++)
     {
      node=CreateElement();
      if(node==NULL)
         return(false);
      Add(node);
      result&=node.Load(file_handle);
     }
//--- 成功
   return(result);
  }

我们可以看到,Type() 方法只是返回一个值。

   virtual int       Type(void) const { return(0x7779); }

在 SB 中,这样的检查有什么必要?读取类型并创建相应类型的元素真的就足够了吗?

 
Alexey Viktorov #:
this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

好吧,如果类型没有读取,下一步该怎么办?

代码如下:

//--- 通过调用节点对象的 Load() 方法,依次重新创建列表项
   this.Clear();
   for(uint i=0; i<num; i++)
     {
      //--- 读取并检查对象数据起始标记 - 0xFFFFFFFFFFFFFFFFFFFFFFF
      if(::FileReadLong(file_handle)!=MARKER_START_DATA)
         return false;
      //--- 读取对象类型
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);
      node=this.CreateElement();
      if(node==NULL)
         return false;
      this.Add(node);
      //--- 现在,文件指针相对于对象标记的起始位置偏移了 12 个字节(8 - 标记,4 - 类型)。
      //--- 让我们将指针指向对象数据的开头,并使用节点元素的 Load() 方法从文件中加载对象属性。
      if(!::FileSeek(file_handle,-12,SEEK_CUR))
         return false;
      result &=node.Load(file_handle);
     }
//--- 结果
   return result;
  }
//+------------------------------------------------------------------+
//| 创建列表项的方法|
//+------------------------------------------------------------------+
CObject *CListObj::CreateElement(void)
  {
//--- 根据 m_element_type 中的对象类型,创建一个新对象
   switch(this.m_element_type)
     {
      case OBJECT_TYPE_TABLE_CELL   :  return new CTableCell();
      case OBJECT_TYPE_TABLE_ROW    :  return new CTableRow();
      case OBJECT_TYPE_TABLE_MODEL  :  return new CTableModel();
      default                       :  return NULL;
     }
  }

将对象的类型读入一个变量。然后我们尝试在 CreateElement() 中创建这个对象,结果出现了一些情况。如果没有从文件中读取创建对象的类型,该方法会返回什么?

 
Artyom Trishkin #:

那么,如果类型没有读取,接下来该怎么办?

代码如下

我们将对象的类型读入一个变量。然后,我们尝试在 CreateElement() 中创建这个对象,结果出现了一些情况。如果没有从文件中读取创建对象的类型,该方法会返回什么结果?

Artem,我说的不是这个。我说的是 SB 中存在类型检查这一事实。正是这种检查。

//---读取和检查类型
   if(FileReadInteger(file_handle,INT_VALUE)!= Type())
      return(false);

从文件中读取的类型是否与 Type()读取和 类型检查 方法中的类型一致。是这样转换的吗?
而你只是读取类型,并没有进行检查。

那么问题来了:这个检查的深层含义是什么?

 
Alexey Viktorov #:
问题是:这种检查的深层含义是什么?

当调用 SomeObject 的 Load() 方法从文件中加载 SomeObject 类时,它会检查 "我是否真的从文件中读取了自己?如果没有,就意味着出了问题,所以就没有必要继续加载了。

我这里的是一个从文件中读取对象类型的列表(CListObj)。列表不知道文件中有什么(什么对象)。但它必须知道该对象类型,才能在 CreateElement() 方法中创建该对象。这就是它不检查从文件中加载的对象类型的原因。毕竟,Type() 方法返回的是列表类型,而不是对象类型。

 
Artyom Trishkin #:

当调用 SomeObject 的 Load() 方法从文件中加载 SomeObject 类时,它会检查 "我是否真的从文件中读取了自己?如果没有,就意味着出错了,所以没有必要继续加载。

我这里所使用的是一个从文件中读取对象类型的列表(CListObj)。列表不知道文件中有什么(什么对象)。但它必须知道该对象类型,才能在 CreateElement() 方法中创建该对象。这就是它不检查从文件中加载的对象类型的原因。毕竟,Type() 方法返回的是列表类型,而不是对象类型。

谢谢,我想明白了,我明白了。

 

我读了一遍,又重读了一遍。

是 MVC 中 "模型 "以外的任何东西。例如一些 ListStorage

 
我们言归正传。请保留您的意见。
 
我想知道有没有可能以这种方式获得类似 python 和 R 数据框的数据?在这些表格中,不同列可以包含不同类型的数据(来自一组有限的类型,但包括字符串)。
 
Aleksey Nikolayev #:
我想知道有没有可能以这种方式获得类似 python 和 R 数据框的数据?在这些表格中,不同列可以包含不同类型的数据(来自一组有限的类型,但包括字符串)。

可以。如果我们说的是一个表格的不同列,那么在所述实现中,表格的每个单元格都可以有不同的数据类型。