随笔分类 -  c#

摘要:经过前面八篇文章,五次的重构,对于这个充电宝计费项目的重构基本上已经完成。今天是这一系列的最后一篇文章,我们来讲讲如何对条件表达式进行重构,对于条件表达式的重构比较多的一种重构方式就是利用类的多态性进行重构。接下来我们就要使用该规则对PowerBank类中的GetAmount()与GetFrequentRenterPoints()函数进行重构。 阅读全文
posted @ 2021-08-31 17:30 DotNet菜园 阅读(809) 评论(2) 推荐(2) 编辑
摘要:通过“代码重构与单元测试——“提取方法”重构(三) ”至“代码重构与单元测试——使用“以查询取代临时变量”再次对Statement()方法进行重构(七) ”这几篇文章的几次重构之后,再次对充电宝计费项目的代码进行全局性的观察与分析,我们发现在Rental类中的GetAmount()与GetFrequentRenterPoints()方法中的代码对PowerBank类有较大的依赖。因为这两个方法都只用到了Rental类中的RentedTime属性,而多次用到了PowerBank中的属性或字段。通过上面的分析,我们认为将这两个方法中的代码移到PowerBank类中显得更为合理。接下来,我们继续进行这两个方法的重构——将该部分代码移动到PowerBank类中。 阅读全文
posted @ 2021-08-19 14:04 DotNet菜园 阅读(453) 评论(0) 推荐(0) 编辑
摘要:如果我们要将结果以HTML的形式进行组织的话,我们需要将Statement方法里面的代码进行复制,然后修改result变量的文本组织方式即可。这可能就是我们经常做的事情CTRL+C、CTRL+V。我想很多程序是这样来修改代码的,快速方便,使用这种方式修改代码,方法中的好多临时变量也都要被复制一份,这是完全相同的,这样就容易产生重复的代码。在这种情况下,我们需要使用“Replace Temp with Query”(已查询取代临时变量)的重构手法来取出上图所示的红框中的临时变量。 阅读全文
posted @ 2021-08-14 16:03 DotNet菜园 阅读(409) 评论(0) 推荐(3) 编辑
摘要:经过之前的重构(见文章 代码重构与单元测试——“提取方法”重构(三) 与代码重构与单元测试——对方法的参数进行重构(五) ),我们从Statement()方法中提取了两个方法。观察这两个重构后的方法我们不难看出,这两个封装出来的新方法都只需要一个参数,这个参数就是Rental类的对象。也就是这两个方法都依赖于Rental类,而对该方法所在的当前类不太依赖。之所以会这种情况,是因为这两个方法放错了地方,因为这两个方法放在Customer类中但不依赖与Customer类而依赖于Rental类,那就足以说明这两个方法应该放在Rental类中。 阅读全文
posted @ 2021-08-06 15:33 DotNet菜园 阅读(519) 评论(0) 推荐(1) 编辑
摘要:重构最重要的思想就是普通程序也能写出优秀的程序。重构一个项目的巨大工作量就是修改变量名、提取方法、抽取接口、修改方法参数等简单的工作。作为一个普通的程序就可以通过这些简单且容易完成的工作目标来提升自己的编码能力,加深自己对项目的认知,从而为最高层次的重构打下基础。在这个过程中发现Bug、修改Bug,这不是重构。优化不是重构。强化异常捕捉、增加预防性代码不是重构。让代码更容易测试不是重构——尽管重构能达到相同的效果。这些所有的事都是有益的。但这些都不是重构。 阅读全文
posted @ 2021-07-28 12:46 DotNet菜园 阅读(771) 评论(0) 推荐(2) 编辑
摘要:程序开发过程中,写代码是为了实现需求。当我们的代码通过了编译,只是说明它的语法正确,功能能否实现则不能保证。 因此,当我们的某些功能代码完成后,为了检验其是否满足程序的需求。可以通过编写测试代码,模拟程序运行的过程,检验功能代码是否符合预期。单元测试就是开发者编写一小段代码,检验目标代码的功能是否符合预期。通常情况下,单元测试主要面向一些功能单一的模块进行。 阅读全文
posted @ 2021-07-22 12:27 DotNet菜园 阅读(654) 评论(0) 推荐(2) 编辑
摘要:我们观察 代码重构与单元测试(一)文章中的共享充电宝计费代码中,发现Customer类的Statement ()方法首先需要进行重构。Statement ()方法最大的问题就是这个方法里边做的事情太多,我们第一步就是对其进行拆分。也就是使用重构中的“Extract Method”(提取方法)原则对该方法进行简化和拆分。将Statement ()中可以独立出来的代码进行提取。经过仔细分析后的,我们发现如下图中所框选的代码是一个完整的功能模块,其中框1中的代码是进行单价计算的功能,红框2中的代码是进行积分计算的功能,我们可以将这两块代码分别进行提取并封装成一个新的方法。在封装成新方法时,要给这个新的方法取一个恰当的方法名,见名知意。 阅读全文
posted @ 2021-07-15 14:39 DotNet菜园 阅读(929) 评论(3) 推荐(0) 编辑
摘要:我们已经创建了充电宝计费项目,做为我们这次重构的遗留系统,为了验证我们每次重构的正确性,我们需要一个测试项目,对我们重构的代码进行测试。接下来我们来创建这个测试项目。遗留系统,程序员们为了快速完成需求和上线而写出了最基本的代码,而在功能的不断扩充过程中,以打补丁的方式对代码进行扩充,中间还会面临着开发人员的变更和离职,代码就会越来越臃肿,渐渐的变得难以维护。做遗留系统维护工作的程序员,清理代码是他们的日常工作之一。首要的任务是为此系统编写单元测试,搭建重构的测试保护网,并能够形成可读与可工作的测试用例文档。在发现遗留系统中代码的坏味道时,及时地对代码进行重构,并保证重构的小步前进,稳妥的对代码进行结构上的调整,每次调整完后都要进行测试,确保功能和以前一样,只是代码上看着不同。重构模式和现代化的 IDE里的重构工具使重构变得容易、安全和代价低廉。 阅读全文
posted @ 2021-07-06 15:48 DotNet菜园 阅读(968) 评论(1) 推荐(2) 编辑
摘要:遗留系统,程序员们为了快速完成需求和上线而写出了最基本的代码,而在功能的不断扩充过程中,以打补丁的方式对代码进行扩充,中间还会面临着开发人员的变更和离职。逐渐的,代码就会越来越臃肿,渐渐的变得难以维护。程序员,特别是做遗留系统维护工作的程序员,清理代码是他们的日常工作之一。这是基本工作,是必须要做的。首要的任务是为此系统编写单元测试,搭建重构的测试保护网,并能够形成可读与可工作的测试用例文档。在发现遗留系统中代码的坏味道时,及时地对代码进行重构,并保证重构的小步前进,小规模的、独立的、稳妥的对代码进行结构上的调整,每次调整完后都要进行测试,确保你没有改变代码的行为特征——功能和以前一样,只是代码上看着不同。重构模式和现代化的 IDE里的重构工具使重构变得容易、安全和代价低廉。 阅读全文
posted @ 2021-07-02 16:02 DotNet菜园 阅读(1431) 评论(0) 推荐(2) 编辑
摘要:本示例描述了如何创建一个WCF服务,并宿主在命令行应用程序中,客户端可以访问服务元数据,并以异步的方式消费它。 首先,我们创建了一个WCF服务。关于如何创建WCF服务,可以参考我之前的文章(WCF学习之旅—第三个示例之一(二十七)至WCF学习之旅—第三个示例之五(三十一)) 阅读全文
posted @ 2018-03-06 14:10 DotNet菜园 阅读(1291) 评论(2) 推荐(0) 编辑
摘要:运行程序,如果数据库已经存在,则删除重建。当打开 连接以及单独使用OpenAsync和ExecuteNonQueryAsync方法执行SQL命令时,我们使用了I/O异步操作。 在这个任务完成后,我们创建了一张新的表并插入了一些数据,除了之前提到的方法,我们还使用了ExceuteScalarAsync来异步地从数据库引擎中得到一个标量值,并且使用SqlDataReader.ReadAsync方法来从数据库表中异步地读取数据行。 阅读全文
posted @ 2018-02-22 14:56 DotNet菜园 阅读(4800) 评论(1) 推荐(0) 编辑
摘要:这里我们通过HTTPListener类实现了一个非常简单的WEB服务器。也使用了TCPLISTENER类进行TCP套接字I/O操作。我们配置了监听器接收任何主机到本地机器1234端口的连接。然后在单独的工作线程中启动这个监管器,从而在主线程中可以控制这个监听器。 当使用GetContextAsync方法时会发生异步I/O操作。可惜的是,其并不接收CancellationToken从而实现取消功能。所以如果想关闭这个服务器,只需要调用 _listenter.Abort方法,这将丢弃所有连接并关闭服务器。 阅读全文
posted @ 2018-02-08 14:14 DotNet菜园 阅读(2471) 评论(0) 推荐(0) 编辑
摘要:假设以下场景,如果在客户端运行程序,最的事情之一是有一个响应的用户界面。这意味着无论应用程序发生什么,所有的用户界面元素都要保持 快速运行,用户能够从应用程序得到快速响应。达到这一点并不容易!如果你尝试在Windows系统中打开记事本并加载一个有几兆大小的文档,应用程序窗口将交结一段的时间,因为整个文件要先从硬盘中加载,然后程序才能开始处理用户输入。 阅读全文
posted @ 2018-01-26 15:09 DotNet菜园 阅读(1904) 评论(2) 推荐(0) 编辑
摘要:使用ConcurrentBag创建一个可扩展的爬虫,本示例在多个独立的即可生产任务又可消费任务的工作者间如何扩展工作量。本示例模拟一个爬虫程序。 阅读全文
posted @ 2018-01-16 17:23 DotNet菜园 阅读(1118) 评论(0) 推荐(0) 编辑
摘要:本示例将学习如何创建一个能被多个线程异步处理的一组任务的例子。 阅读全文
posted @ 2018-01-08 14:26 DotNet菜园 阅读(1770) 评论(1) 推荐(2) 编辑
摘要:并行算法有可能非常复杂,并且或多或少涵盖了这些并行集合。线程安全并不是没有代价的。比起System.Collections和System.Collections.Generic命名空间中的经典列表 、集合和数组来说,并发集合会有更大的开销,因此,应该只在需要从多个任务中并发访问集合的时候才使用并发集合。在中等代码中使用并发集合没有意义,因为它们会增加无谓的开销。 阅读全文
posted @ 2018-01-02 16:29 DotNet菜园 阅读(2596) 评论(1) 推荐(1) 编辑
摘要:本示例学习使用await来获取异步操作结果时,同步上下文行为的结节,并如何在何时关闭同步上下文流。 默认情况下,await操作符会尝试捕获同步上下文,并在其中执行代码。使用await操作符不会发生死锁的情况,因为当等待结果时并不会阻塞UI线程。 阅读全文
posted @ 2017-12-27 10:16 DotNet菜园 阅读(1978) 评论(1) 推荐(1) 编辑
摘要:本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步调用 。 阅读全文
posted @ 2017-12-21 14:49 DotNet菜园 阅读(1862) 评论(1) 推荐(3) 编辑
摘要:通过前面的文章,已经学习了怎么使用线程,怎么使用线程同步,怎么使用线程池,怎么使用任务并行库。尽管通过上面的学习,对于线程的使用越来越简单。有没有更简单的方法呢。 C# 5.0之后,微软在c#语言中添加了两个关键字async与await,这是在TPL上面的更高一级的抽象,真正简化了异步编程的编程方式,从而有助于我们编写出真正健壮少bug的异步应用程序。 阅读全文
posted @ 2017-12-18 15:38 DotNet菜园 阅读(3621) 评论(1) 推荐(2) 编辑
摘要:我们学习任务调度程序,通过异步代码与UI进行交互。所以本示例是创建Windows应用程序。 taskScheduler是负责如何执行任务,默认情况下是把task放入线程池中的工作线程中。 阅读全文
posted @ 2017-12-11 16:07 DotNet菜园 阅读(1620) 评论(1) 推荐(2) 编辑