C#中的模块化软件开发

目录

介绍

规格类型

模块

没有模块开发

模块化编程

谓词和类型

契约

类型化编程

接口和抽象

其他语言的签名


介绍

软件设计提升了一系列编程质量:

  • 抽象:表示程序各部分的能力,包括其基本特征的摘要。
  • 封装:暴露公共部分和隐藏抽象私有部分的可能性。
  • 模块化:将程序分解为一组内聚和松散耦合组件的能力。

一些目标:

  • 可维护性:修改和扩展程序是否容易?
  • 可重用性:是否可以避免代码重复?

模块化有助于拥有可扩展、可修改、可移植、可维护、可重用、易懂和灵活的软件。它允许在需要时无缝添加新功能,并删除不需要的功能,从而简化面向用户的软件视图。它允许多个开发人员同时处理不同的模块。它还允许独立测试模块。此外,大型项目变得更容易监控和控制。

C#,如CJava和其他编程语言允许通过不同方式创建模块化软件。在本文中,我们将通过C#中的接口简要探讨模块化软件开发。

规格类型

代码规格可能采用不同的形式:

  • 函数式规格:
    • 应该可以定义包含任何类型的相同对象的集合。
    • 应该可以在集合中添加和删除元素,并判断元素是否属于集合。
  • 非函数式规格:
    • 实现应该在当前计算机上有效运行。
    • 实现应该正确处理任意大小的集合。

这里出现了验证问题:如何检查规格?

以下是接口/类型规格:

public interface ISet<T>{
  ISet<T> Add(ISet<T> s, T e);
  ISet<T> Remove(ISet<T> s, T e);
  ISet<T> Empty();
  bool IsEmpty(ISet<T> s);
  bool Find(ISet<T> s, T e);
  int Length(ISet<T> s);
}

以下是正式规格:

IsEmpty(Empty()) = true
IsEmpty(Add(s, e)) = false
Find(Empty(), e) = false
Find(Add(s, e), e) = true
Find(Add(s, e), e) = Find(s, e)
Add(s, e) = s [if Find(s, e) = true]
[unconstrained otherwise]
Remove(Empty(), e) = Empty()
Remove(Add(s, e), e) = s
Remove(Add(s, e), f) = Add(Remove(s, f), e)

模块

模块是表示代码单元(类型,值,函数和语言允许的任何表达式)并满足以下条件的构造:

  • 接口:模块可以公开提供并需要的组件集合。
  • 封装:模块可以隐藏或抽象其某些组件。

模块集应根据其接口引起的依赖关系连接:

  • 独立性:模块应仅依赖于其依赖关系的接口。

许多编程语言提供的模块仅适用于这些属性的子集:

  • 接口可以提供不同级别的验证:仅限名称(RacketPython),类型(COCaml)。
  • 封装可能不存在(参见Python模块privates)。
  • 接口有时必须随模块一起提供(RacketHaskell)或作为独立公民(COCaml)。

在下面的文章中,我们将研究C#在模块方面的能力。

没有模块开发

所有代码都写在一个单元中,几乎没有规格。

以下是一个例子:

public T[] Empty<T>(){
  return new T[]{};
}
public bool IsEmpty<T>(T[] s){
  return s.Length == 0;
}
public T[] Add<T>(T[] s, T e){
  var l = new List<T>(s);
  l.Add(e);
  return l.ToArray();
}
public T[] Remove<T>(T[] s, T e){
  var l = new List<T>(s);
  l.Remove(e);
  return l.ToArray();
}
public bool Find<T>(T[] s, T e){
  return s.Contains(e);
}
public int Length<T>(T[] s){
  return s.Length;
}

有利的特点:

  • REPL(简化增量开发)。
  • 可扩展语言(简化了编写ad-hoc代码)。

问题:

  • 具有不同目的的部分代码都混合在一个文件中(例如:实现和测试)。
  • 阻碍代码重用/修改子集(例如,修改集合表示)。
  • 使代码验证变得复杂(全部或什么也没有)。
  • 不适合单独编译,单独测试,团队开发。

模块化编程

模块化编程将代码分解为一组内聚和松散耦合的模块,这些模块应根据规格进行组合。

接口/实现类的关系类似于模块/签名

以下是接口/类型规格:

public interface ISet<T>{
  ISet<T> Add(ISet<T> s, T e);
  ISet<T> Remove(ISet<T> s, T e);
  ISet<T> Empty();
  bool IsEmpty(ISet<T> s);
  bool Find(ISet<T> s, T e);
  int Length(ISet<T> s);
}

以下是客户端模块:

public class MySet<T>:ISet<T>{
  public ISet<T> Add(ISet<T> s, T e)    {  /* ... */ }
  public ISet<T> Remove(ISet<T> s, T e) {  /* ... */ }
  public ISet<T> Empty()                {  /* ... */ }
  public bool IsEmpty(ISet<T> s)        {  /* ... */ }
  public bool Find(ISet<T> s, T e)      {  /* ... */ }
  public int Length(ISet<T> s)          {  /* ... */ }
}

以下是测试模块:

public class MySetTest{
  public void AddTest()     {  /* ... */ }
  public void RemoveTest()  {  /* ... */ }
  public void EmptyTest()   {  /* ... */ }
  public void IsEmptyTest() {  /* ... */ }
  public void FindTest()    {  /* ... */ }
  public void LengthTest()  {  /* ... */ }
}

好处:

  • 促进代码重用:测试和客户端都可以使用相同的实现模块。
  • 允许多个实现:客户端可以选择适当的实现模块而无需修改其代码。
  • 确保有效提供所需的功能。
  • 允许多个开发人员同时处理不同的模块。
  • 允许独立测试模块。
  • 大型项目变得更容易监控和控制。

谓词和类型

类型是语言值的子集。例如:bool 类型是集合truefalse}

谓词是一个取任何可能值并返回布尔值的函数:

  • 谓词是类型的特征函数。
  • 谓词通常是具有动态类型检查的语言的符号。

契约

C#中,根据官方文档,契约提供了一种为代码指定前置条件,后置条件和对象不变量的方法。前提条件是输入方法或属性时必须满足的要求。后置条件描述了方法或属性代码退出时的期望。对象不变量描述处于良好状态的类的预期状态。

代码契约包括用于标记代码的类,用于编译时分析的静态分析器和运行时分析器。代码契约的类可以在System.Diagnostics.Contracts命名空间中找到。

代码契约的好处包括:

  • 改进的测试:代码契约提供静态契约验证,运行时检查和文档生成。
  • 自动测试工具:您可以使用代码契约通过过滤掉不符合前提条件的无意义测试参数来生成更有意义的单元测试。
  • 静态验证:静态检查程序可以在不运行程序的情况下决定是否存在任何契约违规。它检查隐式契约,例如null解引用和数组边界,以及显式契约。
  • 参考文档:文档生成器使用契约信息扩充现有XML文档文件。还有可以与Sandcastle一起使用的样式表,   以便生成具有契约部分的文档页面。

类型化编程

类型系统是应用于程序的形式方法,其旨在用类型对程序的元素进行分类,以保证其行为的某些正确性。

根据语言及其编译器,类型系统可能有不同的风格:

  • 动态类型检查:所有验证都在运行时完成,不需要类型注释(RacketPythonRuby)。
  • 静态类型检查:所有验证都在编译时完成,类型注释要么是必需的(C#,CJava),要么是推断的(OCamlHaskell)。

好处:

  • 静态检查类型。
  • Typed类型系统非常具有表现力。

接口和抽象

抽象数据类型是:

  • 组件的抽象和独立表示。
  • 可能是同一抽象的多个不同实现。
  • 可能是同一抽象的多个客户端。

其他语言的签名

Java中的接口:

interface Set<T>{
  Set<T> add(Set<T> set, T e);
  Set<T> remove(Set<T> set, T e);
  Set<T> empty();
  boolean is_empty(Set<T> set);
  boolean find(Set<T> set, T e);
  int length(Set<T> set);
}

OCaml中的签名:

module type SET = sig
  type ’a set
  val add       : ’a set → ’a → ’a set
  val remove    : ’a set → ’a → ’a set
  val empty     : unit → ’a set
  val is_empty  : ’a set → bool
  val find      : ’a set → ’a → bool
  val length    : ’a set → int
end

 

原文地址:https://www.codeproject.com/Articles/5163072/Modular-Software-Development-In-Csharp

第1章 认识C#开发环境 1.1 C#概述 2 1.1.1 C#发展历程 2 1.1.2 C#语言编程环境 2 1.2 .NET Framework 2.0简介 2 1.2.1 什么是.NET Framework 2.0 2 1.2.2 .NET Framework 2.0特性 3 1.3 安装集成开发环境Visual Studio 2005 4 1.3.1 安装Visual Studio 2005开发环境 4 1.3.2 安装MSDN帮助 7 1.3.3 如何使用MSDN帮助 9 1.3.4 利用MSDN帮助附带的示例学习编程 11 1.4 启动Visual Studio 2005开发环境 12 1.4.1 启动Visual Studio 2005 12 1.4.2 创建项目 12 1.5 熟悉Visual Studio 2005集成开发环境 13 1.5.1 新特性 14 1.5.2 主窗口 14 1.5.3 菜单栏 14 1.5.4 工具栏 18 1.5.5 文档窗口 18 1.5.6 工具箱窗口 19 1.5.7 解决方案资源管理器窗口 20 1.5.8 属性窗口 20 1.5.9 代码编辑器 21 1.5.10 “错误列表”面板 22 1.5.11 “输出”面板 22 1.6 程序调试 22 1.6.1 断点操作 22 1.6.2 使用开始、断和停止执行功能调试程序 23 1.6.3 单步执行 25 1.6.4 运行到程序的指定位置 25 第2章 QQ企业通 2.1 设计思路 28 2.2 关键技术 28 2.2.1 INI文件的应用 28 2.2.2 线程的应用 30 2.2.3 在Socket发送大容量的消息 30 2.2.4 将流序列化或反序列化为对象 31 2.2.5 用InnerList列表记录信息 31 2.3 设计过程 32 2.3.1 类库的设计 33 2.3.2 客户端注册模块设计 40 2.3.3 客户端登录模块设计 42 2.3.4 客户端QQ模块设计 43 2.3.5 客户端消息发送模块设计 48 2.3.6 服务器端控制台模块设计 52 第3章 SQL数据表提取器模块 3.1 概述 56 3.2 关键技术 56 3.2.1 如何备份数据库 56 3.2.2 如何还原数据库 57 3.2.3 如何附加数据库 58 3.2.4 如何分离数据库 59 3.2.5 设置数据库模式 59 3.3 设计过程 61 3.3.1 主窗体 61 3.3.2 获取服务器名称 62 3.3.3 获取所有数据库 63 3.3.4 获取所有数据表 64 3.3.5 备份数据库 66 3.3.6 还原数据库 67 3.3.7 附加数据库 68 3.3.8 分离数据库 70 3.3.9 导出表结构 71 3.3.10 导出数据 74 第4章 万能搜索模块 4.1 设计思路 80 4.2 关键技术 80 4.2.1 如何制作一个接口程序 80 4.2.2 实现接口程序的信息互传 80 4.2.3 如何将接口程序加载到其他程序 82 4.2.4 怎样操作RichtextBox控件的选择文本 82 4.2.5 如何获取数据表字段的描述信息 83 4.3 设计过程 83 4.3.1 获取数据表字段的文信息 84 4.3.2 添加数据表的查询条件 86 4.3.3 向SQL语句添加括号 89 4.3.4 查询生成后的SQL语句 90 4.3.5 主程序获得接口信息 92 第5章 万能打印模块 5.1 设计思路 94 5.2 关键技术 94 5.2.1 打印设置(PrintDocument类) 94 5.2.2 打印预览对话框(PrintPreview Dialog) 95 5.2.3 打印对话框(PrintDialog) 96 5.2.4 获取指定颜色值和字体样式 97 5.2.5 DataGridView控件的相关应用 97 5.3 设计过程 98 5.3.1 打印信息的设置 98 5.3.2 表格样式的设置 100 5.3.3 打印类的设置 101 5.3.4 打印数据信息 108 第6章 决策分析模块 6.1 设计思路 112 6.2 关键技术 112 6.2.1 游标的基本操作 112 6.2.2 存储过程的基本操作 115 6.2.3 透视表的基本概念 117 6.2.4 统计表的基本操作 117 6.2.5 单击显示右键菜单 118 6.3 设计过程 118 6.3.1 主窗体的初始化 119 6.3.2 透视表的筛选 127 6.3.3 透视表的设计 130 6.3.4 统计表的设计 132 第7章 自定义图表控件 7.1 设计思路 136 7.2 关键技术 137 7.2.1 控件的生成 137 7.2.2 如何在项目添加控件 137 7.2.3 在“属性”对话框添加属性 137 7.2.4 用GDI+绘制图形 139 7.2.5 如何在控件上绘制图形 143 7.2.6 获取扇形外弧心点的位置 143 7.3 设计过程 144 7.3.1 向自定义控件添加属性 144 7.3.2 获取绘制图表的初始值数据 149 7.3.3 绘制标签框 153 7.3.4 绘制图表的表格 157 7.3.5 绘制条形图 163 7.3.6 绘制面形图 170 7.3.7 绘制饼形图 174 第8章 电子邮件收发模块 8.1 概述 180 8.2 关键技术 180 8.2.1 Base64编码格式 180 8.2.2 SMTP服务 181 8.2.3 POP3协议 184 8.2.4 使用Jmail组件接收邮件 186 8.2.5 邮件发送类的使用 188 8.2.6 使用正则表达式验证邮件格式 190 8.3 设计过程 191 8.3.1 数据库设计 191 8.3.2 系统登录 191 8.3.3 邮件发送实现 192 8.3.4 为邮件上传多个附件 193 8.3.5 邮件接收实现 194 8.3.6 查看邮件详细信息 196 8.3.7 下载附件的实现 197 8.3.8 删除邮件实现 198 8.3.9 用户管理 198 第9章 短信群发模块 9.1 设计思路 202 9.2 关键技术 202 9.2.1 短信猫API函数的使用 202 9.2.2 短信猫的短信接收格式 205 9.2.3 窗体间的互操作 205 9.2.4 锁定模块主窗体 206 9.2.5 使用ADO.NET连接Access数据库 206 9.3 设计过程 207 9.3.1 数据库设计 207 9.3.2 群发短信实现 209 9.3.3 已发送短信管理 213 9.3.4 接收短信实现 215 9.3.5 常用联系人管理 219 9.3.6 常用短语管理 221 第10章 桌面精灵模块 10.1 概述 226 10.2 关键技术 226 10.2.1 阴阳历转换算法 226 10.2.2 调用系统API实现鼠标穿透效果 230 10.2.3 修改注册表控制程序开机自启动 231 10.2.4 通过控制窗体透明度实现日历透明显示效果 231 10.2.5 拖动无标题栏窗体 232 10.2.6 将窗体的关闭位置写入到注册表 232 10.2.7 将程序图标写入到托盘 232 10.3 设计过程 233 10.3.1 桌面精灵模块公共类设计 233 10.3.2 当前日期的农历、天干地支年、节日及星座显示 235 10.3.3 定时提醒的实现 240 10.3.4 日历窗体效果控制 242 10.3.5 转到某天、某周、某月及某年的实现 243 10.3.6 节日管理 245 10.3.7 提醒管理 249 第11章 文件批量处理器 11.1 概述 256 11.2 关键技术 256 11.2.1 文件流技术 256 11.2.2 文件解压缩技术 258 11.2.3 获取系统文件及文件夹图标 262 11.2.4 获取指定目录下的所有文件及文件夹 265 11.2.5 Word操作技术 266 11.2.6 进度条的显示 266 11.2.7 对ListView控件的项进行排序 267 11.3 设计过程 267 11.3.1 主窗体预览 267 11.3.2 批量复制、剪切文件 268 11.3.3 批量复制、剪切文件夹 270 11.3.4 批量重命名文件 271 11.3.5 批量删除文件及文件夹 275 11.3.6 搜索文件及文件夹 276 11.3.7 批量压缩、解压文件 278 11.3.8 分割、合并文件 280 第12章 图片管理工具模块 12.1 概述 286 12.2 关键技术 286 12.2.1 上下移动ListBox选项 286 12.2.2 将文件复制到剪切板 287 12.2.3 格式转换 288 12.2.4 图片幻灯片 288 12.2.5 图片旋转 289 12.3 设计过程 290 12.3.1 主窗体 290 12.3.2 打开图片目录 291 12.3.3 图片格式转换 292 12.3.4 设为桌面背景 294 12.3.5 图片特效 296 12.3.6 图片调节 300 12.3.7 图片水印 304 12.3.8 幻灯片放映 306 12.3.9 图片打印 308 第13章 FTP文件管理模块 13.1 设计思路 312 13.2 关键技术 312 13.2.1 架设FTP服务器 312 13.2.2 登录FTP服务器 317 13.2.3 获取服务器上文件的大小 318 13.2.4 向FTP服务器发送命令 319 13.2.5 调用系统API 321 13.3 设计过程 322 13.3.1 主窗体设计 322 13.3.2 登录FTP服务器 323 13.3.3 获取本地磁盘 325 13.3.4 获取指定磁盘的文件 326 13.3.5 获取本地磁盘文件的图标 327 13.3.6 获取FTP服务器的所有文件 329 13.3.7 批量上传文件 333 13.3.8 批量下载文件 337 13.3.9 删除FTP的文件或文件夹 340 第14章 魔法兔子模块 14.1 概述 344 14.2 关键技术 344 14.2.1 获取进程信息 344 14.2.2 获取计算机信息 347 14.2.3 修改注册表 349 14.3 设计过程 349 14.3.1 主窗体 349 14.3.2 功能菜单设计 350 14.3.3 系统检测 353 14.3.4 系统优化 356 14.3.5 超级工具 360 14.3.6 实用工具 367 14.3.7 任务管理器 369 14.3.8 选项设置 371 第15章 学生考试模块 15.1 设计思路 376 15.2 关键技术 376 15.2.1 获取试题数目 376 15.2.2 验证用户名和密码 377 15.2.3 随机抽取试题 377 15.2.4 自动评分 377 15.3 设计过程 378 15.3.1 数据库设计 378 15.3.2 公共类设计 380 15.3.3 登录验证 381 15.3.4 主窗体实现 382 15.3.5 开始考试 384 15.3.6 修改密码 393 15.3.7 分数查询 394 15.3.8 管理员界面 394 15.3.9 用户管理 395 15.3.10 成绩查询 399 15.3.11 考试设置 401 15.3.12 添加试题 403 15.3.13 修改试题 406 第16章 网页浏览器模块 16.1 概述 410 16.2 关键技术 410 16.2.1 网页浏览器核心控件 410 16.2.2 网页多页面显示 415 16.2.3 获取网页源码 416 16.3 设计过程 417 16.3.1 主窗体 417 16.3.2 查看网页源码 427 16.3.3 添加到收藏夹 427 16.3.4 整理收藏夹 429 第17章 电话客服管理模块 17.1 设计思路 432 17.2 关键技术 432 17.2.1 语音卡的API函数 432 17.2.2 硬件语音卡驱动分析 437 17.2.3 窗体间传值 438 17.2.4 导航菜单的制作 438 17.3 设 计 过 程 439 17.3.1 数据库设计 439 17.3.2 模块主窗体设计 441 17.3.3 自动语音处理 444 17.3.4 通话管理实现 450 17.3.5 员工管理实现 452 17.3.6 产品类别管理 455 第18章 多媒体播放器 18.1 设计思路 460 18.2 关键技术 460 18.2.1 窗体间的信息传递 460 18.2.2 AxWindowsMediaPlayer控件的相关应用 461 18.2.3 在列表框动态移动选的项 463 18.2.4 如何在文件夹遍历文件 463 18.2.5 如何实现播放进度条 464 18.3 设计过程 465 18.3.1 磁性窗体的设置 465 18.3.2 播放窗体的设计 472 18.3.3 列表窗体的设计 482 18.3.4 歌词窗体的设计 485 第19章 屏幕录像模块 19.1 概述 488 19.2 关键技术 488 19.2.1 如何抓取屏幕 488 19.2.2 创建AVI文件 488 19.2.3 向AVI文件添加视频 489 19.2.4 分解AVI文件 490 19.2.5 设置快捷键 491 19.3 设计过程 494 19.3.1 主窗体设计 494 19.3.2 抓图功能 494 19.3.3 选项设置 496 19.3.4 屏幕录像 497 19.3.5 视频分割 503 第20章 EXE文件加密器 20.1 设计思路 512 20.2 关键技术 512 20.2.1 FileStream对象 512 20.2.2 文件的读写操作 513 20.2.3 如何获取两个日期的月份差 515 20.2.4 获取两个日期的相差天数 516 20.2.5 载取字符串的指定字符 516 20.3 设计过程 517 20.3.1 获取加密字符串的信息 517 20.3.2 对生成后的数据进行加密 520 20.3.3 对EXE文件进行加密 522 20.3.4 解密文件的设置 524 第21章 视频监控模块 21.1 设计思路 530 21.2 关键技术 530 21.2.1 认识视频监控卡 530 21.2.2 视频监控卡API函数的使用 532 21.2.3 Pelco-D协议 536 21.2.4 串口通信技术 538 21.2.5 WMI类的使用 540 21.2.6 注册表技术 541 21.3 设计过程 543 21.3.1 视频监控实现 543 21.3.2 云台控制 546 21.3.3 色彩控制 548 21.3.4 图像抓拍及生成监控录像 549 21.3.5 定时录像设置 551 21.3.6 录像回放 552 21.3.7 注册程序 553 21.3.8 实时监控软件运行时间及磁盘空间 554 第22章 网络五子棋游戏 22.1 设计思路 558 22.2 关键技术 558 22.2.1 在下拉列表绘制图片 558 22.2.2 UDP协议 560 22.2.3 用Socket实现信息传递的必备条件 560 22.2.4 自定义事件的设置 561 22.2.5 动态按钮的设置 562 22.3 设计过程 564 22.3.1 类库的设计 564 22.3.2 客户端注册模块设计 569 22.3.3 客户端登录模块设计 571 22.3.4 五子棋大厅的设计 573 22.3.5 对决窗体的设计 583 22.3.6 网络五子棋服务器窗体的设计 598 第23章 在线升级模块 23.1 设计思路 610 23.2 关键技术 610 23.2.1 FTP上传下载技术 610 23.2.2 XML文件操作 611 23.2.3 INI文件的读写 613 23.2.4 动态生成版本面板 614 23.2.5 使用Hashtable(哈希表)记录版本号及更新信息 614 23.3 类库设计过程 615 23.4 服务器端设计过程 621 23.4.1 服务器端主窗体预览 621 23.4.2 连接FTP服务器 622 23.4.3 向FTP服务器上传新版本 623 23.5 客户端设计过程 626 23.5.1 启动客户端时检测是否有新版本 626 23.5.2 从FTP服务器下载指定版本 628 23.5.3 定时升级设置 630 第24章 Windows应用程序打包与部署境 24.1 Windows Installer简介 634 24.2 Windows应用程序部署 634 24.2.1 创建部署项目 634 24.2.2 可选的部署功能 636 24.3 安装及卸载Windows程序 642 24.3.1 在本地计算机上安装 642 24.3.2 部署到其他计算机 642 24.3.3 卸载安装应用程序 642
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值