用户界面编程简化方法

在软件开发过程中,与用户的交互是不可或缺的一部分。无论是直接的图形用户界面(GUI)还是间接的命令行界面(CLI),都需要程序员投入大量的时间和精力去实现。本文介绍一种通过抽象类简化用户界面编程的方法,这种方法不仅可以减少程序员的工作量,还可以提供多种用户界面实现方式,包括文本基础和图形用户界面等。

几乎每个程序都需要某种方式与用户进行通信。那些不需要与用户通信的程序(如驱动程序、系统进程等)仍然可以从与开发人员通信中受益,这使得调试过程变得更加容易。实现这些功能通常需要程序员特别注意,从而导致繁琐且耗时的工作。

但是,这种工作量可以大大减少。毕竟,用户所做的唯一事情就是改变变量和调用函数。因此,一个最优的解决方案就是告诉机器哪些变量和函数需要对用户公开(发布)。然后,与用户的通信可以导出到其他标准一次性实现的代码中,从而节省了程序员的工作。换句话说,程序员只需要坚持使用基础设施定义的(非常少的)函数,而不必担心用户界面的实现。

这种方法还允许用户界面的不同实现,提供了极大的灵活性。这些实现不仅可以在基于文本和图形之间变化,还可以在用户提示、配置文件、命令行开关、网络协议等之间变化。

基础设施

本文介绍的基础设施基于一个名为ui_export抽象类。任何想要向用户发布一些成员变量的类都需要继承这个类。通过这样做,它需要实现addoptions函数。addoptions的实现应该只包含对postoption函数的调用,该函数也是从ui_export继承的。

每个要发布的选项都需要在addoptions中调用postoption函数。它有14种不同的实现,允许发布不同类型的数据和函数。

以下示例说明了上述函数的调用方式:

class car : public ui_export { ... class engine eng; void start() {}; int weight; bool _lights; bool getlights() { return (_lights); } void setlights(bool par) {_lights=par; repaint();} ... void addoptions() { postoption("eng", "manipulate the engine object", ŋ); postoption("start", "start the car", this, &car::start); postoption("weight", "weight of the car in kg", &weight); postoption("lights", "headlights of the car", this, &car::getlights, &car::setlights); } };

完成这些后,类就可以被用户界面使用了。

用户界面

随代码提供的这个用户界面是基于文本的。它只使用C++标准库,这使得它与平台无关。由于基础设施的面向类方法,它具有菜单驱动的感觉。

用户界面的基础是一个名为user_interface的类。要使用它,需要创建该类的实例。作为ui_export的子类,user_interface实现了所有的postoption函数。这些函数用于初始化用户界面。operator()函数启动用户界面。

user_interface ui; ui.postoption("o", "manipulate obj", &obj); ui.postoption(...); ... ui();

就是这样。

示例

以下是'Demo1YourApp.cpp'的简化版本。它展示了使用用户界面的简单程序的样子:

#include "UI.hpp" class yourClass : public ui_export { public: bool b; int i; void addoptions() { postoption("b", "mess with a boolean", &b); postoption("i", "mess with an integer", &i); } }; int main(int argc, char* argv) { yourClass c; user_interface ui; ui.postoption("yourClass", "mess around with yourClass", &c); ui(); }

保存功能

用户界面有一个简单的“保存状态”机制。它可以用于初始化应用程序,但不适合实际保存复杂应用程序的状态(启动需要很长时间)。当用户界面退出时,它会询问用户是(Q)退出(不保存)还是(S)保存(并退出)。

它的工作原理是简单地记住所有用户输入并将其保存在文件中。在启动时,用户界面打开文件(默认文件名为'input')并执行之前保存的所有输入。可以通过用户界面对象访问加载和保存文件的文件名:

ui.loadfilename = "init"; ui.savefilename = "save";

保存文件的名称也可以在用户界面执行期间更改。这是通过默认发布的SaveFile选项完成的。

还可以手动编辑包含已保存输入的保存文件。

C++标准库

与基础设施概念相关的另一个真正的好处是,像C++标准库这样的通用库可以预先发布为UI-capable。这再次减少了程序员的工作量,并确保了不同程序的统一行为,这对用户来说是很好的。

已经开始了。文件stdUI.hpp旨在构建UI-capable类,这些类沿着C++标准库类在命名空间stdUI中。以下类已经可用:

  • stdUI::vector
  • stdUI::ios_base
  • stdUI::basic_ios
  • stdUI::basic_istream
  • stdUI::basic_ostream
  • stdUI::basic_iostream
  • stdUI::basic_stringstream
  • stdUI::basic_fstream

非基本版本也是可用的。

优点:

  • 不再需要完全实现用户交互机制
  • 程序员只需要知道(非常少的)基础设施命令
  • 允许多种用户界面实现(基于文本的、图形的、配置文件解析、命令行开关)
  • 简单的初始化或状态保存功能
  • 不同程序的通用用户体验
  • 程序参数的大量可编辑性(对调试有好处,对用户来说可能不好)
  • 像C++标准库这样的通用库可以预先发布,进一步减少工作量
  • 代码非常面向类(参见模块化编程的评论)
  • 没有信息隐藏/一旦发布选项就无法隐藏
  • (导致大型项目变得有些“选项膨胀”)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485