首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要类设计帮助

需要类设计帮助
EN

Stack Overflow用户
提问于 2009-01-18 23:48:52
回答 7查看 606关注 0票数 1

我是编程新手,所以我想我应该从那些了解它的人那里得到帮助。

我目前正在编写一个注册申请,基本上将采取用户输入,验证输入的数据,显示审查屏幕(用户必须打印出来,并在副本中邮寄),然后将输入的信息保存到数据库中。

以下是需要捕获和保存的字段。

代码语言:javascript
复制
public class Person 
{
   private string id;
   private string currentLastName;
   private string currentFirstName;
   private string currentMiddleName;
   private string currentSuffixtName;

   private string formerLastName;
   private string formerFirstName;
   private string formerMiddleName;
   private string formerSuffixtName;

   private string currentAddressNumber;
   private string currentAddressDirection;
   private string currentAddressStreet;
   private string currentAddressStreetType;
   private string currentAddressAptNum;
   private string currentAddressrCity;
   private string currentAddressState;
   private string currentAddressZipcode;
   private string currentAddressCounty;

   private string formerAddressNumber;
   private string formerAddressDirection;
   private string formerAddressStreet;
   private string formerAddressStreetType;
   private string formerAddressAptNum;
   private string formerAddressrCity;
   private string formerAddressState;
   private string formerAddressZipcode;
   private string formerAddressCounty;

   private string mailAddressLineOne;
   private string mailAddressLineTwo;
   private string mailAddressLineThree;

   private DateTime birthdate;
   private string gender;
    private string HomePhone;
    private string WorkPhone;
    private string CellPhone;
    private string FaxNumber;
   private string driversLicense;
   private string ssNumber;
   private string membershipType;
   private DateTime registrationDate;
   private string ipAddress;
   private string browserInfo; 
}

再看一眼之后,我想我应该把通用的东西分离出来,为每个类创建一个类,让一个人拥有每个类或每个类的一个接口。即

代码语言:javascript
复制
public interface IName
{
    string getLastName();
    string getFirstName();
    string getMiddleName();
    string getSuffixName();
}

    public class Name : IName
{
    private string _lastName;
    private string _firstName;
    private string _middleName;
    private string _suffixName;

    // Validation Methods
    // private set methods

    //#region IName Members
}


public interface IAddress
{
    string getAddressNumber();
    string getAddressDirection();
    string getAddressStreet();
    string getAddressStreetType();
    string getAddressAptNum();
    string getAddressCity();
    string getAddressState();
    string getAddressZipcode();
    string getAddressCounty();
}

public class Address : IAddress
{
    private string _addressNumber;
    private string _addressDirection;
    private string _addressStreet;
    private string _addressStreetType;
    private string _addressAptNum;
    private string _addressrCity;
    private string _addressState;
    private string _addressZipcode;
    private string _addressCounty;

    // Validation Methods
    // private Set Methods
    // public get methods


    //#region IAddress Members
}
public interface IPerson
{
    int getId();
    IName getCurrentName();
    IName getFormerName();

    IAddress getCurrentAddress();
    IAddress getFormerAddress();
    IAddress getMailingAddress();

    DateTime getBirthdate();
    string getGender();
    string getSSNumber();
    string getPersonType();
    DateTime getRegistrationDate();
    string getIPAddress();
    string getBrowserInfo();
    string getDriversLicense();

    string getHomePhone();
    string getWorkPhone();
    string getCellPhone();
    string getFaxNumber();
    string getEmailAddress();
    string getSecondaryEmailAddress();

    bool save();
    void load();

}

public class Person : IPerson
{
    private int _id;
    private IName _currentName;
    private IName _formerName;

    private IAddress _currentAddress;
    private IAddress _formerAddress;
    private IAddress _mailingAddress;

    private DateTime _birthdate;
    private string _gender;
    private string _ssNumber;
    private string _personType;
    private DateTime _registrationDate;
    private string _ipAddress;
    private string _browserInfo;
    private string _driversLicense;

    private string _homePhone;
    private string _workPhone;
    private string _cellPhone;
    private string _faxNumber;
    private string _emailAddress;
    private string _secondaryEmailAddress;


    // private set methods

    // #region IPerson Members
    // .... Get Methods 
    public bool save()
    {
        DataLayer dl = new DataLayer();
        if (_id == 0)
            return dl.insertPerson(this);
        else
            return dl.updatePerson(this);
    }
}

下面是我的数据层插入方法

代码语言:javascript
复制
public bool insertPerson(IPerson person)
{
    bool inserted = false;
    SqlConnection cnDB = DatabaseConnection.GetOpenDBConnection();
    try
    {
        SqlCommand cmDB = new SqlCommand("sp_InsertName", cnDB);
        cmDB.CommandType = CommandType.StoredProcedure;
        cmDB.Parameters.Add("@last_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@last_name"].Value = person.getCurrentName().getLastName();
        cmDB.Parameters.Add("@first_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@first_name"].Value = person.getCurrentName().getFirstName();
        cmDB.Parameters.Add("@middle_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@middle_name"].Value = person.getCurrentName().getMiddleName();
        cmDB.Parameters.Add("@suffix_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@suffix_name"].Value = person.getCurrentName().getSuffixName();
        int id = cmDB.ExecuteNonQuery();

        cmDB = new SqlCommand("sp_InsertName", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@last_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@last_name"].Value = person.getFormerName().getLastName();
        cmDB.Parameters.Add("@former_first_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@former_first_name"].Value = person.getFormerName().getFirstName();
        cmDB.Parameters.Add("@middle_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@middle_name"].Value = person.getFormerName().getMiddleName();
        cmDB.Parameters.Add("@suffix_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@suffix_name"].Value = person.getFormerName().getSuffixName();
        cmDB.ExecuteNonQuery();

        // Insert Current Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getCurrentAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getCurrentAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getCurrentAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getCurrentAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getCurrentAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getCurrentAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getCurrentAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getCurrentAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getCurrentAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // Insert Former Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getFormerAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getFormerAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getFormerAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getFormerAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getFormerAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getFormerAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getFormerAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getFormerAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getFormerAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // Insert Mailing Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getMailingAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getMailingAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getMailingAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getMailingAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getMailingAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getMailingAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getMailingAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getMailingAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getMailingAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // insert Personal Info

        cmDB = new SqlCommand("sp_InsertPersonalInfo", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@birthdate", System.Data.SqlDbType.DateTime);
        cmDB.Parameters["@birthdate"].Value = person.getBirthdate();
        cmDB.Parameters.Add("@gender", System.Data.SqlDbType.VarChar, 1);
        cmDB.Parameters["@gender"].Value = person.getGender();
        cmDB.Parameters.Add("@ss_number", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@ss_number"].Value = person.getSSNumber();
        cmDB.Parameters.Add("@person_type", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@person_type"].Value = person.getPersonType();
        cmDB.Parameters.Add("@registration_date", System.Data.SqlDbType.DateTime);
        cmDB.Parameters["@registration_date"].Value = person.getRegistrationDate();
        cmDB.Parameters.Add("@ip_address", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@ip_address"].Value = person.getIPAddress();
        cmDB.Parameters.Add("@browser_info", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@browser_info"].Value = person.getBrowserInfo();
        cmDB.Parameters.Add("@drivers_license", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@drivers_license"].Value = person.getDriversLicense();
        cmDB.ExecuteNonQuery();

        //insert email address contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Email";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@gender"].Value = person.getEmailAddress();
        cmDB.ExecuteNonQuery();

        //insert secondary email address contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Secondary Email";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@gender"].Value = person.getSecondaryEmailAddress();
        cmDB.ExecuteNonQuery();

        //insert home phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Home Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getHomePhone();
        cmDB.ExecuteNonQuery();

        //insert work phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Work Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getWorkPhone();
        cmDB.ExecuteNonQuery();

        //insert cell phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Cell Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getCellPhone();
        cmDB.ExecuteNonQuery();

        //insert cell phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Fax Number";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getFaxNumber();
        cmDB.ExecuteNonQuery();


        inserted = true;
    }
    catch (SqlException sqlEx)
    {
        throw new Exception(GetSqlExceptionMessage(sqlEx.Number));
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        if (cnDB.State == ConnectionState.Open)
            cnDB.Close();
    }
    return inserted;
}

编辑:我觉得这段代码以后很难维护。有没有人能帮我想出一种更简单、更易维护的方法呢?在添加记录之后,我也不知道该如何更新记录。

提前感谢您的帮助

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-03-25 16:57:15

首先,如果您想简化维护,我将考虑使用ORM进行映射。我会看看nHibernate、Linq2Sql、实体框架或其他十亿左右的东西。它将从上面去除大量的噪音。

第二个建议是继续你正在做的重构。我喜欢你填写地址的方式,如果你看你的人,一个人没有以前的名字,你的所作所为就是在你的域模型中泄露了跟踪以前信息的要求。我将把所有这些都移出,并定义一个DTO,它将具有两个属性:

代码语言:javascript
复制
public class PersonDTO
{
    public Person Current;
    Public Person Previous;
}

我认为这消除了很多噪音。我也喜欢使用字典来处理多个电话号码,基本上我们有:

代码语言:javascript
复制
public class Phone
{
   PhoneType PhoneType;
   string Number
   string AreaCode
   string Extension
}

有些人可能会让手机有数字,所以我不想争论这一点,或者你可以像你一样只有一个字符串。需要记住的一件事是,如果这适用的话,就是Internaitonalization。

现在在我个人身上,我会有一个字典,这允许您在遍历电话字典时将四个插入操作分解为一个循环。如果您有帐单或收货地址,我会使用类似的模型。

如果您不使用ORM,那么使用sql参数帮助遵守DRY的一种方法很简单。以下代码不是用来编译的,而只是向您展示了一种模式,以再次最小化噪声:

代码语言:javascript
复制
public class DALLayer
{
   public void InsertPerson(Person p)
   {
       using (SqlCommand sqlCmd=CreateNewCommand())
       {
           AddPersonParams(p,sqlCmd);
           sqlCmd.ExecuteNonQuery();
       }
   }

   public void UpdatePerson(Person p)
   {
       using (SqlCommand sqlCmd=CreateNewCommand())
       {
           AddPersonParams(p,sqlCmd);
           //We add the Id since we have it in updates but not in inserts
           sqlCmd.AddParameter("@PersonId",p.Id);
           sqlCmd.ExecuteNonQuery();
       }

   }

   private void AddPersonParams(Person p, Sqlcommand sqlCmd)
   {
       //Do all the code to add Params which exists in both insert and updates
   }

}

现在,您所做的工作已经合并,因此当您向person添加新属性时,在处理参数时只需修改一个函数。

还有一件事要插入你现在和以前的地址,你不是干的。你可以这样做:

代码语言:javascript
复制
private void InserAddress(Address address, int Id, AddressType addType)
{

}

现在,从您的insert Person例程中,您将调用此方法两次:

代码语言:javascript
复制
InsertAddress(p.CurrentAddress,id,CurrentAddress);
InsertAddress(p.FormerAddress,id,FormerAddress);

当然,如果你采纳我之前的建议,这看起来可能会非常不同。

编辑

我完全错过了这一点,但我想强调一下Chris所说的(我+1你觉得这是一件非常好的事情,我不得不重复一遍。使用属性:-)

票数 3
EN

Stack Overflow用户

发布于 2009-03-24 17:21:27

根据您列出的需求,您似乎不需要对应用程序中的数据进行太多操作。特别地,看起来其中一些可以被视为与用户相关联的数据列表,即姓名、地址和电话的列表。您发布的数据访问代码似乎已经以这种方式构造,我认为在您的场景中,您没有必要使应用程序的逻辑面变得更加严格。

给定的名字被视为与人相关的数据列表,我认为您不希望将它的第一个插入作为创建用户的部分。您还可以将其他信息添加到主记录中,如driversLicense、ssn、出生日期。

对于接口,请考虑您是否从中获得了任何好处。这是一种打破类之间直接依赖关系的好方法,但看起来你在代码中没有这种场景。还要注意,声明接口并不会强制您使用get/set方法,因为您可以要求具有get的属性由类实现。

向列表中使用的每个类添加一个type属性。您可以使用它来减少接口和数据访问层中的代码。在后一种方法中,您现在可以循环遍历列表,并以相同的方式插入所有这些元素。

考虑使用一些可以帮助您进行数据访问的工具,比如linq2sql或nhibernate。这将简化数据访问代码,并使其不易出错。

Ps。并不是所有情况都有单一的解决方案,即使在特定的情况下,个人经验也会影响每个人解决问题的方式。有一些实践和原则旨在减少这种情况,但即使这样,也会出现差异。也就是说,我建议你阅读一些关于SOLID、DDD和TDD的信息。它们不是解决这些问题的良方,但学习它们肯定会对软件开发有所帮助。

更新:关于评论中的问题。Linq2sql支持存储过程,请在linq2sql:http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx上查看scott gu的系列文章。通过使用sp,您失去了linq2sql的部分灵活性,但不管怎样,它都会对您有所帮助。

关于更新的问题。有不同的策略,主要问题是关于对相同信息的并发更新。如果并发更新不是问题,那么您可以保留最新版本,因此您只需保存数据即可。在这种情况下,您唯一需要的原始数据是记录的ID,您可以让数据被覆盖。如果需要检测并发更新,则必须保留所有原始值的副本或使用时间戳。sp代码需要在更新记录时检查原始值是否匹配。

可以在设计器中配置linq2sql,以控制正在使用的并发更新策略的类型以及要发送的原始值。可能有一些问题/答案与此相关。如何具体地连接它,将取决于您赋予它的用途(使用它生成的实体或滚动自己的实体,将sp附加到实体或单独使用),甚至取决于您使用的控件,因为其中一些控件可以为您保存原始值(使用viewstate)。

票数 2
EN

Stack Overflow用户

发布于 2009-01-19 01:42:09

我注意到你在使用ASP.NET,你应该知道会员服务提供商可以为你处理所有这些繁琐的工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/456146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档