如何简化代码?

时间:2010-03-24 16:05:08

标签: c# silverlight

我刚刚在C#/ Silverlight中创建了我的第一个主要应用程序。最后,总行数超过12,000行代码。考虑到这是一个php / javascript应用程序的重写,我创建了2年,超过28,000行,我实际上为我的成就感到自豪。

在stackoverflow和其他在线网站上阅读了很多问题和答案后,我遵循了许多海报的建议:我创建了一些课程,程序,以及我一年前复制和粘贴的东西;我创建了逻辑图表以找出复杂的功能;确保没有疯狂的隐藏字符(使用标签代替空格);和其他一些事情;必要时发表评论(我有很多评论)。

我的应用程序包含4个水平布局的图块,用户控件加载到每个图块中。您可以随时加载一到四个切片。如果你有一次切片加载,切片会占用整个画板...如果你有2个加载,每个占用一半,3个三分之一,四分之一。

这些切片中的每一个都代表(为了这个例子)一个光控制。每个切片中都有3个滑块控件。现在,当我编写滑块的功能时,我在公共函数内部使用了一个switch / case语句,该语句将在指定的切片/滑块上运行命令。这使得一些重复的代码,但我看不到它,因为每个切片的命名不同。所以我会做slice1.my.commands(); slice2.my.commands();等。

我的问题是如何进一步清理我的代码? (可悲的是我无法发布任何代码)。有没有办法从我的代码中删除这个重复?

5 个答案:

答案 0 :(得分:11)

您需要的是与您的朋友进行战略模式的界面。例如:

public interface ISlice 
{
    public Slider Slide {get;set;}
}

public class Slice1 : ISlice 
{
    public Slider Slide { get; set; }
}

public static class SliceSlider
{
    public static void DoSomethingCoolWithTheSliceSlide(ISlice slice) 
    {
        slice.Slide.LookitMeIAmLearningDesignPatterns();
    }
} 

答案 1 :(得分:7)

编写更少的代码不应该是您的目标。最后,所有这些都与TCO(总体拥有成本)有关。

虽然拥有更少的代码可以提高TCO,但有一个因素会对TCO产生更大的影响:可维护性。您应该编写最易维护的代码。首先阅读Robert Martin's Clean Code

更新

你也说“我有很多评论”。这是您可以改进代码的一个方面。正如您将从Martin的书中学到的那样,好的代码几乎不需要任何评论。 Martin说“评论是谎言”“应保留用于有关代码和设计的技术说明。”

更新2:

当我添加它时,这是罗伯特·马丁的书中我最喜欢的引用:

  • “一个班级或单元应该只有一个,改变的原因[单一责任原则]” [第138页]
  • “超过三个[方法论据]非常值得怀疑,应该避免偏见。” [第288页]
  • “功能的第一条规则是它们应该很小。功能的第二条规则是它们应该小于它。” [第34页]
  • “函数几乎不应该是20行” [第34页]
  • “函数中的语句都应该以相同的抽象级别编写” [第304页]
  • “应保留有关代码和设计的技术说明的注释。” [第286页]

答案 2 :(得分:2)

我倾向于同意史蒂文。编写更少的代码或更少的行并不总是目标。回想一下史蒂夫·沃兹尼亚克的一些故事,他曾经制作过非常紧凑的硬件,将大量的逻辑放入一个非常小的包装中,但是很少有人能够遵循他的所作所为,维护或制造它。

话虽这么说,我建议你对设计模式非常熟悉。它们可能不会减少您的代码行,但它们可能使您更容易编写,维护和理解代码。很多时候,它们确实减少了你拥有的行数。以下是一些资源:

DoFactory Design Patterns Reference

Wikipedia Design Pattern Acticle

答案 3 :(得分:2)

接口和抽象类是.net平台中非常强大的一部分。

接口只不过是对类的合同要求。即:接口是实现该接口的类必须具有的一组定义的方法和/或属性。界面只是合同声明。

抽象类非常强大,因为您可以将逻辑“转换为”实现该抽象类的类。但那是另一场球赛。

考虑:

public interface ISlice
{
    bool DoStuff(string someParameter);
}

public class MySpecificSliceOfType : ISlice
{
    // this must have a method implementation for the [bool DoStuff(string)] method
    public bool DoStuff(string mySpecificParameter)
    {
       // LOGIC in the Specific class
       return(true);
    }
}

public class MyOtherSliceOfType : ISlice
{
    // this must have a method implementation for the [bool DoStuff(string)] method
    public bool DoStuff(string myOtherParameter)
    {
       // LOGIC in the Other class
       return(true);
    }
}

虽然这是一个非常简单的示例,但在类MySpecificSliceOfType'和'MyOtherSliceOfType'上声明ISlice接口的接口实现意味着必需的DoStuff()方法不管你有哪一个,因为你可以做的事情像:

bool sliceReturn = ((ISlice)currentSlice).DoStuff(currentStringParameterValue);

这可以帮助您解决以下问题:

bool sliceReturn = false;
switch(typeofSlice)
{
    case "other" :
        sliceReturn = MyOtherSliceOfType.DoStuff(currentStrignParamterValue);
        break;
    case "specific" :
        sliceReturn = MySpecificSliceOfType.DoStuff(currentStrignParamterValue);
        break;
}

如果你有>这里说明的点更强大。 2种不同的类型。

接口和抽象类也很好地与C#类型检查相结合。

接口是反射中的一个基础...一些非常谨慎使用的东西,但是因为它可以在特定的情况下节省很多......而且在序列化(也就是序列化)中可以真正帮助你飞了。

答案 4 :(得分:0)

由于你无法真正发布任何代码,我不妨随意抛出。你能把这些切片放到一个数组中吗?如果是这样,您可以通过让每个控件设置一个变量(我称之为whichSlice)来摆脱一些冗余代码。所以控件都将whichSlice设置为正确的数字1-4,然后运行正常的开关并调用slices[whichSlice].my.commands();