C# 这个代码有多糟糕?

C# 这个代码有多糟糕?,c#,.net,asp.net,graffiticms,C#,.net,Asp.net,Graffiticms,好的,我是一个业余程序员,刚刚写了这个。它完成了任务,但我想知道它有多糟糕,可以做什么样的改进 [请注意,这是涂鸦CMS的粉笔扩展。] public string PostsAsSlides(PostCollection posts, int PostsPerSlide) { StringBuilder sb = new StringBuilder(); decimal slides = Math.Round((decimal)posts.Count /

好的,我是一个业余程序员,刚刚写了这个。它完成了任务,但我想知道它有多糟糕,可以做什么样的改进

[请注意,这是涂鸦CMS的粉笔扩展。]

public string PostsAsSlides(PostCollection posts, int PostsPerSlide)
    {
        StringBuilder sb = new StringBuilder();
        decimal slides = Math.Round((decimal)posts.Count / (decimal)PostsPerSlide, 3);
        int NumberOfSlides = Convert.ToInt32(Math.Ceiling(slides));

        for (int i = 0; i < NumberOfSlides; i++ )
        {
            int PostCount = 0;
            sb.Append("<div class=\"slide\">\n");
            foreach (Post post in posts.Skip<Post>(i * PostsPerSlide))
            {
                PostCount += 1;
                string CssClass = "slide-block";

                if (PostCount == 1)
                    CssClass += " first";
                else if (PostCount == PostsPerSlide)
                    CssClass += " last";

                sb.Append(string.Format("<div class=\"{0}\">\n", CssClass));
                sb.Append(string.Format("<a href=\"{0}\" rel=\"prettyPhoto[gallery]\" title=\"{1}\"><img src=\"{2}\" alt=\"{3}\" /></a>\n", post.Custom("Large Image"), post.MetaDescription, post.ImageUrl, post.Title));
                sb.Append(string.Format("<a class=\"button-launch-website\" href=\"{0}\" target=\"_blank\">Launch Website</a>\n", post.Custom("Website Url")));
                sb.Append("</div><!--.slide-block-->\n");

                if (PostCount == PostsPerSlide)
                    break;
            }
            sb.Append("</div><!--.slide-->\n");
        }

        return sb.ToString();
    }
公共字符串PostsAsSlides(PostCollection posts,int PostsPerSlide)
{
StringBuilder sb=新的StringBuilder();
十进制幻灯片=数学四舍五入((十进制)posts.Count/(十进制)PostsPerSlide,3);
int NumberOfSlides=Convert.ToInt32(数学上限(幻灯片));
对于(int i=0;i
这不太好,但我见过更糟的情况

假设这是ASP.Net,您使用这种方法而不是中继器有什么原因吗

编辑:


如果在本例中无法使用转发器,我建议使用.NETHTML类来生成HTML,而不是使用文本。稍后阅读/调整会更容易一些。

如果存在帖子的定义,这会有所帮助,但一般来说,我会说,在Asp.Net中,在代码隐藏中生成HTML不是一种方法

因为它被标记为.Net,所以

要显示集合中的项目列表,最好查看其中一个数据控件(中继器、数据列表等),并学习如何正确使用这些控件


我见过更糟的情况,但你可以改进很多

  • 使用StringBuilder.AppendFormat()代替内部带有string.Format()的StringBuilder.Append()
  • 在它周围添加一些单元测试,以确保它生成您想要的输出,然后重构内部代码以使其更好。测试将确保您没有损坏任何东西

  • 你可以做的另一件事是:用
    sb.AppendFormat(…)
    代替
    sb.Append(string.Format(…)
    调用

            foreach (Post post in posts.Skip<Post>(i * PostsPerSlide))
            {
                // ...
                if (PostCount == PostsPerSlide)
                    break;
            }
    
    事实上,您的两个嵌套循环可能可以在一个循环中处理


    另外,我更喜欢对html属性使用单引号,因为它们是合法的,不需要转义。

    我的第一个想法是,这将很难进行单元测试

    我建议将第二个for循环作为一个单独的函数,这样您就可以得到如下结果:

    for (int i = 0; i < NumberOfSlides; i++ )
            {
                int PostCount = 0;
                sb.Append("<div class=\"slide\">\n");
                LoopPosts(posts, i);
    ...
    
    如果您养成了这样做循环的习惯,那么当您需要进行单元测试时,将内部循环与外部循环分开进行测试将更容易。

    使用而不是StringBuilder来编写HTML:

    StringBuilder sb = new StringBuilder();
    using(HtmlTextWriter writer = new HtmlTextWriter(new StringWriter(sb)))
    {
        writer.WriteBeginTag("div");
        writer.WriteAttribute("class", "slide");
        //...
    }
    return sb.ToString();
    
    我们不希望使用非结构化编写器来编写结构化数据

    将你的内循环主体分成一个单独的例行程序

    foreach(...)
    {
        WritePost(post, writer);
    }
    
    //snip
    
    private void WritePost(Post post, HtmlTextWriter writer)
    {
        //write single post
    }
    
    这使得它更易于测试和修改

    使用数据结构来管理CSS类等内容。

    不要在额外的类名后面加空格,希望所有的类名都排在最后,而是保留一个
    列表
    ,根据需要添加和删除类名,然后调用:

    List<string> cssClasses = new List<string>();
    
    //snip
    
    string.Join(" ", cssClasses.ToArray());
    
    List cssClasses=new List();
    //剪断
    Join(“,cssClasses.ToArray());
    
    我想说,它看起来足够好了,代码没有严重的问题,而且可以很好地工作。但这并不意味着它无法改进

    以下是一些提示:

    对于一般浮点运算,应使用
    double
    而不是
    Decimal
    。但是,在这种情况下,您根本不需要任何浮点运算,只需要整数即可:

    int numberOfSlides = (posts.Count + PostsPerSlide - 1) / PostsPerSlide;
    
    但是,如果只对所有项目使用单个循环,而不是循环中的循环,则根本不需要幻灯片计数

    局部变量的约定是驼峰式(后点)而不是帕斯卡式(后计数)。尽量使变量名有意义,而不是像“sb”这样晦涩难懂的缩写。如果一个变量的作用域很小,你不需要一个有意义的名字,只需要一个尽可能简单的字母,而不是缩写

    您可以直接指定文字字符串,而不是将字符串“滑块”和“第一个”连接起来。这样,您就可以用一个简单的赋值替换对String.Concat的调用。(这接近于过早优化,但另一方面,字符串串联所需的时间要长约50倍。)

    您可以在StringBuilder上使用
    .AppendFormat(…)
    而不是
    .Append(String.Format(…)
    。在这种情况下,我会坚持使用Append,因为实际上没有任何东西需要格式化,您只是连接字符串

    所以,我会这样写方法:

    public string PostsAsSlides(PostCollection posts, int postsPerSlide) {
       StringBuilder builder = new StringBuilder();
       int postCount = 0;
       foreach (Post post in posts) {
          postCount++;
    
          string cssClass;
          if (postCount == 1) {
             builder.Append("<div class=\"slide\">\n");
             cssClass = "slide-block first";
          } else if (postCount == postsPerSlide) {
             cssClass = "slide-block last";
             postCount = 0;
          } else {
             cssClass = "slide-block";
          }
    
          builder.Append("<div class=\"").Append(cssClass).Append("\">\n")
             .Append("<a href=\"").Append(post.Custom("Large Image"))
             .Append("\" rel=\"prettyPhoto[gallery]\" title=\"")
             .Append(post.MetaDescription).Append("\"><img src=\"")
             .Append(post.ImageUrl).Append("\" alt=\"").Append(post.Title)
             .Append("\" /></a>\n")
             .Append("<a class=\"button-launch-website\" href=\"")
             .Append(post.Custom("Website Url"))
             .Append("\" target=\"_blank\">Launch Website</a>\n")
             .Append("</div><!--.slide-block-->\n");
    
          if (postCount == 0) {
             builder.Append("</div><!--.slide-->\n");
          }
    
       }
       return builder.ToString();
    }
    
    公共字符串PostsAsSlides(PostCollection posts,int postsPerSlide){
    StringBuilder=新的StringBuilder();
    int postCount=0;
    foreach(以职位为单位的职位){
    后计数++;
    字符串cssClass;
    如果(后计数==1){
    生成器。追加(“\n”);
    cssClass=“滑块优先”;
    }else if(postCount==postsPerSlide){
    cssClass=“滑块最后一个”;
    后计数=0;
    }否则{
    cssClass=“滑块”;
    }
    builder.Append(“\n”)
    美联社
    
    int numberOfSlides = (posts.Count + PostsPerSlide - 1) / PostsPerSlide;
    
    public string PostsAsSlides(PostCollection posts, int postsPerSlide) {
       StringBuilder builder = new StringBuilder();
       int postCount = 0;
       foreach (Post post in posts) {
          postCount++;
    
          string cssClass;
          if (postCount == 1) {
             builder.Append("<div class=\"slide\">\n");
             cssClass = "slide-block first";
          } else if (postCount == postsPerSlide) {
             cssClass = "slide-block last";
             postCount = 0;
          } else {
             cssClass = "slide-block";
          }
    
          builder.Append("<div class=\"").Append(cssClass).Append("\">\n")
             .Append("<a href=\"").Append(post.Custom("Large Image"))
             .Append("\" rel=\"prettyPhoto[gallery]\" title=\"")
             .Append(post.MetaDescription).Append("\"><img src=\"")
             .Append(post.ImageUrl).Append("\" alt=\"").Append(post.Title)
             .Append("\" /></a>\n")
             .Append("<a class=\"button-launch-website\" href=\"")
             .Append(post.Custom("Website Url"))
             .Append("\" target=\"_blank\">Launch Website</a>\n")
             .Append("</div><!--.slide-block-->\n");
    
          if (postCount == 0) {
             builder.Append("</div><!--.slide-->\n");
          }
    
       }
       return builder.ToString();
    }