Tag: 重构

C#中的字符串基准 – 重构速度/可维护性

我在自己的时间里一直在修补小函数,试图找到重构它们的方法(我最近阅读了Martin Fowler的书“ 重构:改进现有代码的设计” )。 我在更新它附近的代码库的另一部分时发现了以下函数MakeNiceString() ,它看起来像是一个很好的候选人。 事实上,没有真正的理由来替换它,但是它足够小并且做了一些小的事情,因此很容易遵循,但仍然可以获得“良好”的体验。 private static string MakeNiceString(string str) { char[] ca = str.ToCharArray(); string result = null; int i = 0; result += System.Convert.ToString(ca[0]); for (i = 1; i <= ca.Length – 1; i++) { if (!(char.IsLower(ca[i]))) { result += " "; } result += System.Convert.ToString(ca[i]); } return result; } static […]

用多态重构或类似替换条件?

我曾尝试过问过这个问题的变体。 我得到了一些有用的答案,但对我来说仍然没有任何感觉。 在我看来,这不应该是一个难以破解的坚果,但我无法找到一个优雅的简单解决方案。 (这是我以前的post,但请首先尝试将此处所述的问题视为程序代码,以免受早期解释的影响,这些解释似乎导致了非常复杂的解决方案: 成本计算器应用程序的设计模式? ) 基本上,问题是为可能包含许多服务的项目创建一个计算器。 在这种情况下“写作”和“分析”。 对于不同的服务,小时数的计算方式不同:写作是通过将“每个产品”小时数乘以产品数来计算的,项目中包含的产品越多,小时费率越低,但总数小时数逐步累积(即对于中型项目,您可以采用小范围定价,然后将中等价格定价加到实际产品数量上)。 然而,分析它更简单,它只是每个尺寸范围的批量率。 你怎么能将它重构成一个优雅的,最好是简单的面向对象的版本(请注意,我绝不会以纯粹的程序方式这样写它,这只是为了以另一种方式简洁地显示问题)。 我一直在考虑工厂,战略和装饰模式,但不能让任何工作得很好。 (我在前一段时间阅读了Head First Design Patterns,所描述的装饰器和工厂模式都与这个问题有一些相似之处,但我很难看到它们是那里所说的好解决方案。装饰器例子似乎非常复杂,只是添加了调味品,但也许它可以在这里工作得更好,我不知道。至少事实上,小时数的计算逐渐积累,让我想到了装饰模式……以及披萨工厂书中的工厂模式示例。好吧,它似乎创造了这样一个荒谬的类爆炸,至少在他们的例子中。我之前已经找到了很好的工厂模式,但我看不出如何在没有得到一套非常复杂的类的情况下使用它) 主要目标是只需要在一个地方(疏松耦合等)进行更改,如果我要添加一个新参数(比如另一个大小,如XSMALL,和/或其他服务,如“管理”)。 这是程序代码示例: public class Conditional { private int _numberOfManuals; private string _serviceType; private const int SMALL = 2; private const int MEDIUM = 8; public int GetHours() { if (_numberOfManuals <= SMALL) { if (_serviceType == "writing") return 30 […]

如何确定类型是否是一种集合?

我试图确定运行时类型是否是某种集合类型。 我在下面的工作,但似乎很奇怪,我必须将我认为的数据类型命名为数组,就像我所做的那样。 在下面的代码中,通用逻辑的原因是因为,在我的应用程序中,我希望所有集合都是通用的。 bool IsCollectionType(Type type) { if (!type.GetGenericArguments().Any()) return false; Type genericTypeDefinition = type.GetGenericTypeDefinition(); var collectionTypes = new[] { typeof(IEnumerable), typeof(ICollection), typeof(IList), typeof(List) }; return collectionTypes.Any(x => x.IsAssignableFrom(genericTypeDefinition)); } 我如何重构此代码以使其更智能或更简单?

应该何时尝试消除switch语句?

我在我正在处理的代码库中遇到了一个switch语句,我正在试图弄清楚如何用更好的东西替换它,因为switch语句被认为是代码味道 。 但是,通过阅读有关替换 switch 语句的 stackoverflow上的几篇文章,我似乎无法想到替换此特定switch语句的有效方法。 它让我想知道这个特定的switch语句是否正常,以及是否有特殊情况认为switch语句是合适的。 在我的情况下,我正在努力的代码(自然略微混淆)是这样的: private MyType DoSomething(IDataRecord reader) { var p = new MyType { Id = (int)reader[idIndex], Name = (string)reader[nameIndex] } switch ((string) reader[discountTypeIndex]) { case “A”: p.DiscountType = DiscountType.Discountable; break; case “B”: p.DiscountType = DiscountType.Loss; break; case “O”: p.DiscountType = DiscountType.Other; break; } return p; } 谁能建议一种消除这种转换的方法? 或者这是一个适当的开关? 如果是,那么switch语句还有其他适当的用途吗? […]

重构静态类以使用dependency injection

我们需要在具有静态方法的代码中使用非托管库。 我想在我的代码中将库操作作为依赖项引入。 除了具有静态方法之外,库还具有初始化方法和设置方法,两者都是全局的。 因此,我不能将它包装在实例类中,因为如果一个实例更改了设置,则所有其他实例都将受到影响,如果一个实例初始化,则所有其他实例将重新初始化。 我想把它作为一个单独的类引入。 这样它将在一个实例类中,但只有一个实例,因此我不必担心更改设置或初始化。 您如何看待这种方法? 我对dependency injection模式很新,我不确定单例模式是否是一个好的解决方案? 您对类似案例的解决方案是什么? 编辑:初始化也是一个参数,所以我不能只是锁定方法调用,并在每次调用时重新初始化和更改设置。 编辑2:以下是一些方法的签名: public static void Initialize(int someParameter) // Parameter can only be changed by re-initalization which // will reset all the settings back to their default values. public static float[] Method1(int someNumber, float[] someArray) public static void ChangeSetting(string settingName, int settingValue)

在C#中,应该考虑在类之前多少行重构?

一个好的经验法则是我智能地重构超过50行的任何方法。 计数不包括注释和空格,而是实际代码。 我之所以聪明地说,有很多时候,超过50行的课程是可以接受的,不能或不应该改变。 我对课程没有经验法则。 一般来说,我不检查类是否应该重构。 在我目前的项目中,我刚刚完成了一个近4000行的课程。 然而,没有超过50的方法,并且大多数行和方法是私有的,并且不对类外的任何数据起作用。 重构类的经验法则是什么?

重构大型构造函数

我们的域模型中有一些对象,你可以说它们可以说是攻击性的大型构造函数,而且很大,以至于IntelliSense放弃了试图向你展示它… 提示具有50个左右参数的类型,主要是值类型,一些引用类型: public class MyLegacyType { public MyLegacyType(int a1, int a2, int a3, … int a50) // etc { } } 我现在就说,没有这种类型不能改变。 类型本身在逻辑上代表一个实体,这恰好是属性重的。 构造此类型的调用者提供来自多个源的大多数参数,但有些是默认的。 也许有一种模式可以为建筑提供资源而不是结果。 但是,可以改变的是如何创建类型。 目前,我们的代码部分受到以下影响: 该类型缺乏智能感知。 丑陋且难以理解的代码。 合并由于位置的Connascence导致的痛苦。 一个直接的答案是利用可选参数的默认值和命名参数来帮助合并。 我们在某种程度上对其他类型这样做,工作正常。 然而,感觉好像这是完全重构的一半。 另一个明显的解决方案是使用容器类型减少构造函数参数,这些容器类型具有以前是构造函数参数的属性。 这很好地整理了构造函数,并允许您在容器中嵌入默认值,但实际上将问题移到另一个类型上,并且可能与可选/命名参数用法相同。 还有Fluent构造函数的概念……在per属性( WithIntA , WithIntB )或容器类型( WithTheseInts(IntContainer c) )的基础上。 就个人而言,我喜欢这种来自呼叫方的方法,但是在大型类型上它又变得冗长,感觉好像我刚刚移动了一个问题而不是解决问题。 我的问题是,如果有一个埋在这个烂摊子里的是: 这些问题的可行的重构策略是什么? 请通过一些相关经验,陷阱或批评来充实任何答案。 我倾向于Fluent的东西,因为我认为它看起来很酷,而且非常易读且易于合并。 我觉得好像我错过了构造函数重构的圣杯 – 所以我愿意接受建议。 当然,这也可能只是一个令人遗憾和不可避免的副作用,首先是拥有这么多属性的类型……

从字符串数学表达式中提取变量

我想用c#从数学表达式中提取变量。 我写了这段代码,它的工作正常: List Variables = new List(); string temp = string.Empty; Console.WriteLine(“Please enter ur expression”); string Expression = Console.ReadLine().Trim(); int Index; for (Index = 0; Index 0) { Variables.Add(temp); temp = string.Empty; } } } if (temp.Length > 0) { Variables.Add(temp); } foreach (string item in Variables) { Console.WriteLine(item); } Console.ReadKey(); 我必须从表达式中检测SIN和COS,因此我将从变量中删除SIN和COS。 这是好方法吗? 是否可以使用正则表达式或更好的方法来执行此操作? 这段代码需要重构吗? […]

在c#中执行此通用抽象类的最佳方法是什么?

我知道我做得不对,但我也知道有办法做到这一点。 我试图尽可能地通用和抽象,否则我的代码将变得非常混乱。 所以我在这里使用策略模式作为GetAggregateClient()方法。 我想要一个名为AbstractAggregate的抽象类,以便它使用generics。 将使用的类型是一系列数据类,即BlogItem,ResourceItem和AskItem。 这些数据类都inheritance自ListItem。 这就是背景信息。 这里的问题是我希望GetAbstractAggregate()返回一个实现AbstractAggregate的客户端类的实例,其中指定的项目类型取决于传入的枚举。但是,我不能返回“AbstractAggregate”。 编译器不会让我这样,因为AbstractAggregateFactory类不是通用的。 有没有人有最好的方法来做到这一点? 非常感谢。 public static class AggregateHelper { public enum AggregateTypes { TankTruckBlog, AskTankTruck, Resources } } public static class AbstractAggregateFactory { public static AbstractAggregate GetAggregateClient(AggregateHelper.AggregateTypes type) { switch (type) { case AggregateHelper.AggregateTypes.AskTankTruck: return new AskTankTruckAggregate(); case AggregateHelper.AggregateTypes.TankTruckBlog: return new TankTruckBlogAggregate(); case AggregateHelper.AggregateTypes.Resources: return new ResourcesAggregate(); default: […]

将换行符附加到字符串的最佳方法除了最后一个

我一直在寻找迭代字符串列表的最佳/最干净的方法,然后创建一个由换行符分隔的字符串(除了最后一行)。 像这样: String 1 String 2 String 3 我在这里写了两个循环,在字符串的末尾有一个换行符(我想避免)和另一个不循环的换行符。 这个不仅对我来说不是“干净”。 我认为有一种更简单的方法可以使逻辑几乎与在字符串末尾有一个新行的示例中一样简单。 List errorMessages = new List(); string messages = “”; //Adds newline to last string. Unwanted. foreach(string msg in errorMessages) { messages += msg + “\n”; } messages = “”; bool first = true; //Avoids newline on last string foreach (string msg in errorMessages) { […]