需要对我的软件架构提出了一些建议。 [code评论] [英] Need some suggestions on my softwares architecture. [Code review]

查看:122
本文介绍了需要对我的软件架构提出了一些建议。 [code评论]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个开源的C#库的其他开发者使用。我重点关注的是易用的。这意味着使用直观的名称,直观的方法使用和这样

I'm making an open source C# library for other developers to use. My key concern is ease of use. This means using intuitive names, intuitive method usage and such.

这是我第一次做了一些与其他人记住,所以我真的很关心建筑的质量。另外,我不介意学习一两件事。 :)

This is the first time I've done something with other people in mind, so I'm really concerned about the quality of the architecture. Plus, I wouldn't mind learning a thing or two. :)

我有三个类别: 下载器,分析器和电影

我在想,这将是最好只露出Movie类我的图书馆,并具有下载器和分析器的调用是隐藏的。

I was thinking that it would be best to only expose the Movie class of my library and have Downloader and Parser remain hidden from invocation.

最后,我看到我的库正在使用这个样子。

Ultimately, I see my library being used like this.

使用FreeIMDB;

using FreeIMDB;

public void Test()
{
    var MyMovie = Movie.FindMovie("The Matrix");
    //Now MyMovie would have all it's fields set and ready for the big show.
}

您可以回顾一下我打算这一点,并指出我所做的任何错误的判断调用和在那里我能得到改善。

Can you review how I'm planning this, and point out any wrong judgement calls I've made and where I could improve.

记住,我主要关注的是易用性。

Movie.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;


namespace FreeIMDB
{
    public class Movie
    {
        public Image Poster { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Rating { get; set; }
        public string Director { get; set; }
        public List<string> Writers { get; set; }
        public List<string> Genres { get; set; }
        public string Tagline { get; set; }
        public string Plot { get; set; }
        public List<string> Cast { get; set; }
        public string Runtime { get; set; }
        public string Country { get; set; }
        public string Language { get; set; }

        public Movie FindMovie(string Title)
        {
            Movie film = new Movie();
            Parser parser = Parser.FromMovieTitle(Title);

            film.Poster = parser.Poster();
            film.Title = parser.Title();
            film.ReleaseDate = parser.ReleaseDate();
            //And so an so forth.
        }

        public Movie FindKnownMovie(string ID)
        {
            Movie film = new Movie();
            Parser parser = Parser.FromMovieID(ID);

            film.Poster = parser.Poster();
            film.Title = parser.Title();
            film.ReleaseDate = parser.ReleaseDate();
            //And so an so forth.
        }
    }
}

Parser.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;

namespace FreeIMDB
{
    /// <summary>
    /// Provides a simple, and intuitive way for searching for movies and actors on IMDB.
    /// </summary>
    class Parser
    {
        private Downloader downloader = new Downloader();                
        private HtmlDocument Page;

        #region "Page Loader Events"
        private Parser()
        {

        }

        public static Parser FromMovieTitle(string MovieTitle)
        {
            var newParser = new Parser();
            newParser.Page = newParser.downloader.FindMovie(MovieTitle);
            return newParser;
        }

        public static Parser FromActorName(string ActorName)
        {
            var newParser = new Parser();
            newParser.Page = newParser.downloader.FindActor(ActorName);
            return newParser;
        }

        public static Parser FromMovieID(string MovieID)
        {
            var newParser = new Parser();
            newParser.Page = newParser.downloader.FindKnownMovie(MovieID);
            return newParser;
        }

        public static Parser FromActorID(string ActorID)
        {
            var newParser = new Parser();
            newParser.Page = newParser.downloader.FindKnownActor(ActorID);
            return newParser;
        }
        #endregion

        #region "Page Parsing Methods"
        public string Poster()
        {
            //Logic to scrape the Poster URL from the Page element of this.
            return null;
        }

        public string Title()
        {
            return null;
        }

        public DateTime ReleaseDate()
        {
            return null;
        }        
        #endregion        
    }
}

-----------------------------------------------

难道你们觉得我走向一个很好的路径,还是我自己设置了为世界伤害以后?

-----------------------------------------------

Do you guys think I'm heading towards a good path, or am I setting myself up for a world of hurt later on?

我最初的想法是分开的下载,分析和实际填充轻松拥有一个可扩展库。试想一下,如果有一天,该网站改变了它的HTML,然后我会只需要modifiy解析类不接触Downloader.cs或Movie.cs类。

My original thought was to separate the downloading, the parsing and the actual populating to easily have an extensible library. Imagine if one day the website changed its HTML, I would then only have to modifiy the parsing class without touching the Downloader.cs or Movie.cs class.

感谢您的阅读和帮助!

任何其他的想法?

推荐答案

您的API大多是静态的,这意味着你是在和自己在未来的可维护性的问题。这是因为静态方法实际上是单身,<一个href="http://stackoverflow.com/questions/2662842/dependency-injection-singleton-design-pattern/2663030#2663030">which有一些显著的缺点的。

Your API is mostly static, meaning you are setting yourself up for maintainability issues in the future. This is because the static methods are actually singletons, which have some significant drawbacks.

我建议争创更多的基于实例的,解耦方法。这自然分离其执行每个操作的定义,留有余地扩展和配置。一个API的易于使用的特性测量不仅公共表面,而且其适应性。

I suggest striving for a more instance-based, decoupled approach. This will naturally separate the definition of each operation from its implementation, leaving room for extensibility and configuration. An API's ease-of-use is measured not only by its public surface, but also by its adaptability.

下面是如何,我会去设计这个系统。首先,定义一些东西,负责获取电影:

Here is how I would go about designing this system. First, define something which is responsible for fetching movies:

public interface IMovieRepository
{
    Movie FindMovieById(string id);

    Movie FindMovieByTitle(string title);
}

接下来,定义一些东西,是负责下载HTML文件:

Next, define something which is responsible for downloading HTML documents:

public interface IHtmlDownloader
{
    HtmlDocument DownloadHtml(Uri uri);
}

然后,定义存储库的实现,它采用的是下载工具:

Then, define a repository implementation which uses a downloader:

public class MovieRepository : IMovieRepository
{
    private readonly IHtmlDownloader _downloader;

    public MovieRepository(IHtmlDownloader downloader)
    {
        _downloader = downloader;
    }

    public Movie FindMovieById(string id)
    {
        var idUri = ...build URI...;

        var html = _downloader.DownloadHtml(idUri);

        return ...parse ID HTML...;
    }

    public Movie FindMovieByTitle(string title)
    {
        var titleUri = ...build URI...;

        var html = _downloader.DownloadHtml(titleUri);

        return ...parse title HTML...;
    }
}

现在,你需要的地方下载电影,你可以在 IMovieRepository 完全取决于而不直接连接到所有的实现细节下方:

Now, anywhere you need to download movies, you can depend solely on IMovieRepository without being directly coupled to all the implementation details beneath it:

public class NeedsMovies
{
    private readonly IMovieRepository _movies;

    public NeedsMovies(IMovieRepository movies)
    {
        _movies = movies;
    }

    public void DoStuffWithMovie(string title)
    {
        var movie = _movies.FindMovieByTitle(title);

        ...
    }
}

另外,你现在可以轻松地测试分析逻辑,而不必进行网络通话。只需保存的HTML,并创建一个下载这使得它到存储库:

In addition, you can now easily test the parsing logic without having to make web calls. Simply save the HTML and create a downloader which gives it to a repository:

public class TitleHtmlDownloader : IHtmlDownloader
{
    public HtmlDocument DownloadHtml(Uri uri)
    {
        return ...create document from saved HTML...
    }
}

[Test]
public void ParseTitle()
{
    var movies = new MovieRepository(new TitleHtmlDownloader());

    var movie = movies.GetByTitle("The Matrix");

    Assert.AreEqual("The Matrix", movie.Title);

    ...assert other values from the HTML...
}

这篇关于需要对我的软件架构提出了一些建议。 [code评论]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆