Недавно, Я сделал сообщение о разработчиках, с которыми я работаю, неправильно использующих блоки try catch , и к сожалению использующих блоки try ... catch в критических ситуациях и игнорирующих ошибку исключения все вместе. вызывает у меня сильную боль в сердце. Вот пример одного из нескольких тысяч разделов кода, в котором они это делали (какой-то код, который не имеет особого значения:
public void AddLocations(BOLocation objBllLocations)
{
try
{
dbManager.Open();
if (objBllLocations.StateID != 0)
{
// about 20 Paramters added to dbManager here
}
else
{
// about 19 Paramters added here
}
dbManager.ExecuteNonQuery(CommandType.StoredProcedure, "ULOCATIONS.AddLocations");
}
catch (Exception ex)
{
}
finally
{
dbManager.Dispose();
}
}
Это абсолютно отвратительно, на мой взгляд, и не уведомляет пользователя в случае возникновения потенциальной проблемы. Я знаю, что многие люди говорят, что ООП - это зло, и что добавление нескольких слоев увеличивает количество строк кода и усложняет программу, что приводит к возможным проблемам с поддержкой кода. Лично я во многом программировал, применяя в этой области почти тот же подход. Ниже я перечислил базовую структуру того, как я обычно кодирую в такой ситуации, и я делал это на многих языках в моей карьере, но этот конкретный код написан на C #. Но приведенный ниже код является хорошей базовой идеей о том, как я использую Объекты, мне кажется, это работает, но, поскольку это хороший источник некоторых довольно интеллектуальных программных мин, я хотел бы знать, стоит ли мне переоценивать это Техника, которую я использовал в течение многих лет. Главным образом потому, что в ближайшие несколько недель я собираюсь погрузиться в не очень хороший код от сторонних разработчиков и модифицировать огромные участки кода. Я хотел бы сделать это как можно лучше. извините за длинный код ссылки.
// *******************************************************************************************
/// <summary>
/// Summary description for BaseBusinessObject
/// </summary>
/// <remarks>
/// Base Class allowing me to do basic function on a Busines Object
/// </remarks>
public class BaseBusinessObject : Object, System.Runtime.Serialization.ISerializable
{
public enum DBCode
{ DBUnknownError,
DBNotSaved,
DBOK
}
// private fields, public properties
public int m_id = -1;
public int ID { get { return m_id; } set { m_id = value; } }
private int m_errorCode = 0;
public int ErrorCode { get { return m_errorCode; } set { m_errorCode = value; } }
private string m_errorMsg = "";
public string ErrorMessage { get { return m_errorMsg; } set { m_errorMsg = value; } }
private Exception m_LastException = null;
public Exception LastException { get { return m_LastException; } set { m_LastException = value;} }
//Constructors
public BaseBusinessObject()
{
Initialize();
}
public BaseBusinessObject(int iID)
{
Initialize();
FillByID(iID);
}
// methods
protected void Initialize()
{
Clear();
Object_OnInit();
// Other Initializable code here
}
public void ClearErrors()
{
m_errorCode = 0; m_errorMsg = ""; m_LastException = null;
}
void System.Runtime.Serialization.ISerializable.GetObjectData(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
//Serialization code for Object must be implemented here
}
// overrideable methods
protected virtual void Object_OnInit()
{
// User can override to add additional initialization stuff.
}
public virtual BaseBusinessObject FillByID(int iID)
{
throw new NotImplementedException("method FillByID Must be implemented");
}
public virtual void Clear()
{
throw new NotImplementedException("method Clear Must be implemented");
}
public virtual DBCode Save()
{
throw new NotImplementedException("method Save Must be implemented");
}
}
// *******************************************************************************************
/// <summary>
/// Example Class that might be based off of a Base Business Object
/// </summary>
/// <remarks>
/// Class for holding all the information about a Customer
/// </remarks>
public class BLLCustomer : BaseBusinessObject
{
// ***************************************
// put field members here other than the ID
private string m_name = "";
public string Name { get { return m_name; } set { m_name = value; } }
public override void Clear()
{
m_id = -1;
m_name = "";
}
public override BaseBusinessObject FillByID(int iID)
{
Clear();
try
{
// usually accessing a DataLayerObject,
//to select a database record
}
catch (Exception Ex)
{
Clear();
LastException = Ex;
// I can have many different exception, this is usually an enum
ErrorCode = 3;
ErrorMessage = "Customer couldn't be loaded";
}
return this;
}
public override DBCode Save()
{
DBCode ret = DBCode.DBUnknownError;
try
{
// usually accessing a DataLayerObject,
//to save a database record
ret = DBCode.DBOK;
}
catch (Exception Ex)
{
LastException = Ex;
// I can have many different exception, this is usually an enum
// i do not usually use just a General Exeption
ErrorCode = 3;
ErrorMessage = "some really weird error happened, customer not saved";
ret = DBCode.DBNotSaved;
}
return ret;
}
}
// *******************************************************************************************
// Example of how it's used on an asp page..
protected void Page_Load(object sender, EventArgs e)
{
// Simplifying this a bit, normally, I'd use something like,
// using some sort of static "factory" method
// BaseObject.NewBusinessObject(typeof(BLLCustomer)).FillByID(34);
BLLCustomer cust = ((BLLCustomer)new BLLCustomer()).FillByID(34);
if (cust.ErrorCode != 0)
{
// There was an error.. Error message is in
//cust.ErrorMessage
// some sort of internal error code is in
//cust.ErrorCode
// Give the users some sort of message through and asp:Label..
// probably based off of cust.ErrorMessage
//log can be handled in the data, business layer... or whatever
lab.ErrorText = cust.ErrorMessage;
}
else
{
// continue using the object, to fill in text boxes,
// literals or whatever.
this.labID = cust.ID.toString();
this.labCompName = cust.Name;
}
}
Суть в том, что мой вопрос таков: не слишком ли сложно усложнить работу со множественными слоями и унаследованными классами, или моя старая иллюстрированная концепция все еще работает хорошо и стабильно? Есть ли лучший способ сделать это сейчас? Должен ли я просто делать прямые вызовы SQL из кода страницы asp.net за страницами, как предлагал коллега-разработчик (хотя это последнее решение заставляет меня чувствовать себя странно), вместо того, чтобы проходить через бизнес-объект и уровень данных (уровень данных не показано, но в основном содержит все сохраненные вызовы процедур). Да, еще один разработчик спросил меня, почему я делаю многоуровневую работу, когда вы можете просто напечатать то, что вам нужно, прямо в коде * .aspx.cs за страницей, и тогда я получу удовольствие от более чем 1 тыс. Строк кода позади. Какой совет здесь?