Организация взаимодействия бизнесс-объектов в ASP.NET
От: Alex Getman  
Дата: 20.06.06 11:56
Оценка:
Hi all.

Интересует следующий вопрос — есть информационная система с Web интерфейсом, написанная на ASP.NET 1.1, в данный момент архитектура разеделна на слои классов/объктов которые отвечают за бизнесс-логику, доступ к данным etc.

Взаимодейтсвие объктов обеспечивается следующим образом — для текущей сессии Юзера создаются экземпляры сущностей (Orgunit, Employee, Report etc.) которые используют сессию для хранения своего состояния, тоесть каждый объект реализует что-то вроде:


public class SalaryDetailReport
{
  private static readonly string sessionId = "OrganizationHierarchy.Payroll.Reports.SalaryDetailReport"; 
  public static SalaryDetailReport Current
  {
    get
        {
      if (HttpContext.Current.Session[SalaryDetailReport.sessionId] != null)
          {
            SalaryDetailReport report = (SalaryDetailReport)HttpContext.Current.Session[SalaryDetailReport.sessionId];
            return report;
      }
          else
      {
            SalaryDetailReport report = new SalaryDetailReport();
        HttpContext.Current.Session[SalaryDetailReport.sessionId] = report;
            return report;
           }
  }
 set
 {
  HttpContext.Current.Session[SalaryDetailReport.sessionId] = value;
  }
}


Вообщем-то сейчас работает нормально, но меня интересует насколько "правильным" можно назвать такой подход к организации взаимодействия бизнесс-объектов?

Может быть у кого-то есть опыт альтернативных решений? Имеет ли смыл особо критичные части для призводительности системы переписать для того, чтобы обеспечить сохранение объектов в Cache по ключу уникальному для каждой сессии пользователя?
Re: Организация взаимодействия бизнесс-объектов в ASP.NET
От: pt4h Беларусь http://dzmitryhuba.blogspot.com/
Дата: 20.06.06 12:56
Оценка: 1 (1)
Здравствуйте, Alex Getman, Вы писали:

AG>Hi all.

Доброго времени суток.

AG>Интересует следующий вопрос — есть информационная система с Web интерфейсом, написанная на ASP.NET 1.1, в данный момент архитектура разеделна на слои классов/объктов которые отвечают за бизнесс-логику, доступ к данным etc.

Разделение на слои есть правильно безусловно.

AG>Взаимодейтсвие объктов обеспечивается следующим образом — для текущей сессии Юзера создаются экземпляры сущностей (Orgunit, Employee, Report etc.) которые используют сессию для хранения своего состояния, тоесть каждый объект реализует что-то вроде:



AG>
AG>public class SalaryDetailReport
AG>{
AG>  private static readonly string sessionId = "OrganizationHierarchy.Payroll.Reports.SalaryDetailReport"; 
AG>  public static SalaryDetailReport Current
AG>  {
AG>    get
AG>        {
AG>      if (HttpContext.Current.Session[SalaryDetailReport.sessionId] != null)
AG>          {
AG>            SalaryDetailReport report = (SalaryDetailReport)HttpContext.Current.Session[SalaryDetailReport.sessionId];
AG>            return report;
AG>      }
AG>          else
AG>      {
AG>            SalaryDetailReport report = new SalaryDetailReport();
AG>        HttpContext.Current.Session[SalaryDetailReport.sessionId] = report;
AG>            return report;
AG>           }
AG>  }
AG> set
AG> {
AG>  HttpContext.Current.Session[SalaryDetailReport.sessionId] = value;
AG>  }
AG>}
AG>

Приведенный кусок кода очень напоминает паттерн Singleton. Если каждый объект в Вашем приложении является "глобальным", возможно необходимо пересмотреть архитектуру.

AG>Вообщем-то сейчас работает нормально, но меня интересует насколько "правильным" можно назвать такой подход к организации взаимодействия бизнесс-объектов?

К сожалению не могу назвать этот подход правильным. Вот несколько причин (не вдаваясь в подробности работы бизнесс объектов):
  1. Пользователь может сменить компьютер и все бизнесс объекты будут пересозданы заново, хотя пользователь возможно ожидал "предыдущего" поведения.
  2. Сессия "плохо" масштабируется. Чтобы достичь масштабируемости необходимо либо заставить пользователя носить с собой все объеты, что осерьезно увеличивает трафик, либо выделять под хранение сессии отдельный сервер.
  3. Если постоянно не сохраняют свое состояние в перманентное хранилище (база данных, напиример), то в случае сбоя возможна потеря данных (что часто бывает неприемлимо).
  4. Если сессия используется в качестве кэша объектов, опять же возможна работа пользователя с устаревшими данными. Вопрос кэширования обсуждается здесь
    Автор: снежок
    Дата: 14.06.06
    и здесь
    Автор: Joker6413
    Дата: 16.06.06
    . В целом даже кэширование следует применять в пределах одного запроса.
  5. Использование внутри самого объекта логики кэширования приводит к тому, что при необходимости изменить политику кэширования Вам придется переписать все объекты. Это должен делать "кто-то" один. Посмотрите в сторону паттерна Repository (Martin Fowler).
  6. Применение ASP.NET специфичной средств (HTTP session) приводит к тому, что Ваши объекты не могут быт ьснова использоаны, скажем, в декстоп приложениях. В целом бизнесс объекты не должны обладать такими знанями как сессия.

AG>Может быть у кого-то есть опыт альтернативных решений? Имеет ли смыл особо критичные части для призводительности системы переписать для того, чтобы обеспечить сохранение объектов в Cache по ключу уникальному для каждой сессии пользователя?

Возможно более правильным решением будет работать с объектами в пределах обработки одного запроса к серверу и дальше "отпускать" их. Представьте ситуацию в которой есть следующий объект:

public class EmployeeYearReport
{
  public int[] Data
    {
      get
        {
          // Тут возвращается масссив с миллионами записей
        }
    }
}


Тогда кэширование таких объектов приведет к исключетельно нерациональному расходованию ресурсов (память сервера, сетевой канал и т.д.). Кэш распухент и будет мешать "ходить".

То есть после того, как Вы закончили работать с объектом сохраните его в базу данных и при соледующем HTTP запросе поднимите его из базы и снова работайте с ним. Потому что сервер базы данных очень просто масштабировать в случае, когда база данных станет "узким местом" Вашей системы.
Боишься — не делай, делаешь — не бойся.
Re[2]: Организация взаимодействия бизнесс-объектов в ASP.NE
От: Alex Getman  
Дата: 20.06.06 14:04
Оценка:
спасибо за подробный ответ.

P>Приведенный кусок кода очень напоминает паттерн Singleton. Если каждый объект в Вашем приложении является

P>"глобальным", возможно необходимо пересмотреть архитектуру.

Объект является глобальным в смысле сессии Юзера. Тоесть каждый пользователь работает с выбранным Orgunit, Report, а хранилищем для объекта (между вызовами страниц) является HTTP Session, так как сессия уникальна, объекты юзеров не пересекаются.


P>
  • Пользователь может сменить компьютер и все бизнесс объекты будут пересозданы заново, хотя пользователь возможно ожидал "предыдущего" поведения.

    вот здесь я не понял. если юзер сменил компьютер — он должен залогинится в систему, его сессия создается заново, объекты инициализируются и т.д.

    P>
  • Сессия "плохо" масштабируется. Чтобы достичь масштабируемости необходимо либо заставить пользователя носить с собой все объеты, что осерьезно увеличивает трафик, либо выделять под хранение сессии отдельный сервер.
    P>
  • Если постоянно не сохраняют свое состояние в перманентное хранилище (база данных, напиример), то в случае сбоя возможна потеря данных (что часто бывает неприемлимо).
    P>
  • Использование внутри самого объекта логики кэширования приводит к тому, что при необходимости изменить политику кэширования Вам придется переписать все объекты. Это должен делать "кто-то" один. Посмотрите в сторону паттерна Repository (Martin Fowler).
    P>
  • Применение ASP.NET специфичной средств (HTTP session) приводит к тому, что Ваши объекты не могут быт ьснова использоаны, скажем, в декстоп приложениях. В целом бизнесс объекты не должны обладать такими знанями как сессия.
    P>[/list]

    с перечисленным согласен.

    P>То есть после того, как Вы закончили работать с объектом сохраните его в базу данных и при соледующем HTTP запросе поднимите его из базы и снова работайте с ним. Потому что сервер базы данных очень просто масштабировать в случае, когда база данных станет "узким местом" Вашей системы.


    тут не согласен. по-моему опыту лучше 10 метров в памяти чем одно обращение к базе, база может находится на физически другом сервере, что повлечет большие расходы на траффик + безопасность.


    Ок, я возможно не совсем понятно описал в первом посте, попробую сказать чего хотелось бы добится на данном этапе:

    1. Например, есть aspx страничка, для ввода приказа. Пользователь заходит на нее, вводит данные и нажимает Submit. Данные нужно проверять, информировать Юзера об ошибках и сохранять при повторном Submit.

    2. Существует несколько сущностей, которые создаются на протяжении нескольких итераций Юзера с разными страницами aspx (что-то вроде визарда) Опять же, не хочется вставлять в код непосредственно странички вызовы OracleCommand и постоянно дергать базу.

    3. Для обеспечения всей этой функциональности хочется построить красивую объктную модель на стороне C# — в коде Page будет только вызовы меотдов класса Order:


    // Submit click
    
    myOrder.Date = DateTimeTextBox.Value;
    
    if (!myOrder.Valid())
     return;
    
    myOrder.Save();



    проблема в том, как наиболее эфективно сохранять объекты между вызовами ASP.NET странички?

    p.s. если я что-то не совсем ясно описал, please feel free to ask about details :)
  • Re[3]: Организация взаимодействия бизнесс-объектов в ASP.NE
    От: pt4h Беларусь http://dzmitryhuba.blogspot.com/
    Дата: 20.06.06 14:39
    Оценка:
    Здравствуйте, Alex Getman, Вы писали:

    AG>спасибо за подробный ответ.


    P>>Приведенный кусок кода очень напоминает паттерн Singleton. Если каждый объект в Вашем приложении является

    P>>"глобальным", возможно необходимо пересмотреть архитектуру.

    AG>Объект является глобальным в смысле сессии Юзера. Тоесть каждый пользователь работает с выбранным Orgunit, Report, а хранилищем для объекта (между вызовами страниц) является HTTP Session, так как сессия уникальна, объекты юзеров не пересекаются.


    P>>
  • Пользователь может сменить компьютер и все бизнесс объекты будут пересозданы заново, хотя пользователь возможно ожидал "предыдущего" поведения.

    AG>вот здесь я не понял. если юзер сменил компьютер — он должен залогинится в систему, его сессия создается заново, объекты инициализируются и т.д.


    P>>
  • Сессия "плохо" масштабируется. Чтобы достичь масштабируемости необходимо либо заставить пользователя носить с собой все объеты, что осерьезно увеличивает трафик, либо выделять под хранение сессии отдельный сервер.
    P>>
  • Если постоянно не сохраняют свое состояние в перманентное хранилище (база данных, напиример), то в случае сбоя возможна потеря данных (что часто бывает неприемлимо).
    P>>
  • Использование внутри самого объекта логики кэширования приводит к тому, что при необходимости изменить политику кэширования Вам придется переписать все объекты. Это должен делать "кто-то" один. Посмотрите в сторону паттерна Repository (Martin Fowler).
    P>>
  • Применение ASP.NET специфичной средств (HTTP session) приводит к тому, что Ваши объекты не могут быт ьснова использоаны, скажем, в декстоп приложениях. В целом бизнесс объекты не должны обладать такими знанями как сессия.
    P>>[/list]

    AG>с перечисленным согласен.


    P>>То есть после того, как Вы закончили работать с объектом сохраните его в базу данных и при соледующем HTTP запросе поднимите его из базы и снова работайте с ним. Потому что сервер базы данных очень просто масштабировать в случае, когда база данных станет "узким местом" Вашей системы.


    AG>тут не согласен. по-моему опыту лучше 10 метров в памяти чем одно обращение к базе, база может находится на физически другом сервере, что повлечет большие расходы на траффик + безопасность.

    Это решение не масштабируется. Оно может работать только в пределах одного сервера.

    AG>Ок, я возможно не совсем понятно описал в первом посте, попробую сказать чего хотелось бы добится на данном этапе:


    AG>1. Например, есть aspx страничка, для ввода приказа. Пользователь заходит на нее, вводит данные и нажимает Submit. Данные нужно проверять, информировать Юзера об ошибках и сохранять при повторном Submit.

    При работе с базой данных все происходит точно в таком порядке — сначала валидация данных, вывод сообщений об ошибке, после корректировки данных создание объекта и запись его в базу.

    AG>2. Существует несколько сущностей, которые создаются на протяжении нескольких итераций Юзера с разными страницами aspx (что-то вроде визарда) Опять же, не хочется вставлять в код непосредственно странички вызовы OracleCommand и постоянно дергать базу.

    Промежуточные объекты вполне могут жить или в сессии, или во вьюстейте, или в базе.

    AG>3. Для обеспечения всей этой функциональности хочется построить красивую объктную модель на стороне C# — в коде Page будет только вызовы меотдов класса Order:

    Объектная модель никак не зависит от способа хранения экземпляров классов, ее составляющих.

    // Submit click
    // Перед изменением объект загружается из базы данных.
    string orderId = this.Request.Params["OrderId"];
    Order myOrder = Order.Load(orderId);
    // Изменяется
    myOrder.Date = DateTimeTextBox.Value;
    
    if (!myOrder.Valid())
     return;
    // Сохраняется
    myOrder.Save();



    AG>проблема в том, как наиболее эфективно сохранять объекты между вызовами ASP.NET странички?

    Оперативная память — это временной хранилище. Наиболее надежным и правильным вариантом будет хранить данные в базе данных.

    AG>p.s. если я что-то не совсем ясно описал, please feel free to ask about details
    Боишься — не делай, делаешь — не бойся.
  • Re[4]: Организация взаимодействия бизнесс-объектов в ASP.NE
    От: Alex Getman  
    Дата: 20.06.06 15:12
    Оценка:
    Здравствуйте, pt4h, Вы писали:

    P>Это решение не масштабируется. Оно может работать только в пределах одного сервера.

    Ok, не страшно, в моем случае это будет единственный сервер.

    P>Промежуточные объекты вполне могут жить или в сессии, или во вьюстейте, или в базе.

    так все-таки могут? :)

    P>Объектная модель никак не зависит от способа хранения экземпляров классов, ее составляющих.

    это поянтно, но хочется избежать постояного разрушения/воссоздания объекта из базы.

    P>
    P>// Submit click
    P>// Перед изменением объект загружается из базы данных.
    P>string orderId = this.Request.Params["OrderId"];
    P>Order myOrder = Order.Load(orderId);
    P>// Изменяется
    P>myOrder.Date = DateTimeTextBox.Value;
    
    P>if (!myOrder.Valid())
    P> return;
    P>// Сохраняется
    P>myOrder.Save();
    P>


    а если в таблице миллион записей? Order.Load(orderId); — будет выполнятся довольно долго, может в этом случае все же имеет смыл хранить объект myOrder в сессии, чтобы не вычитывать его из базы при каждом новом Submit странички?


    в целом, как я понял, Ваше решение бОльший упор делает на сохраняемость и масштабируемость экземпляров бизнесс-объектов, а для небольших решений вполне подойдет использование сессии.
    Re[5]: Организация взаимодействия бизнесс-объектов в ASP.NE
    От: pt4h Беларусь http://dzmitryhuba.blogspot.com/
    Дата: 21.06.06 06:59
    Оценка:
    Здравствуйте, Alex Getman, Вы писали:

    Всегда есть решения больше, чем одно — нам надо только выбрать какое-то .

    AG>Здравствуйте, pt4h, Вы писали:


    P>>Это решение не масштабируется. Оно может работать только в пределах одного сервера.

    AG>Ok, не страшно, в моем случае это будет единственный сервер.

    P>>Промежуточные объекты вполне могут жить или в сессии, или во вьюстейте, или в базе.

    AG>так все-таки могут?

    P>>Объектная модель никак не зависит от способа хранения экземпляров классов, ее составляющих.

    AG>это поянтно, но хочется избежать постояного разрушения/воссоздания объекта из базы.

    P>>
    P>>// Submit click
    P>>// Перед изменением объект загружается из базы данных.
    P>>string orderId = this.Request.Params["OrderId"];
    P>>Order myOrder = Order.Load(orderId);
    P>>// Изменяется
    P>>myOrder.Date = DateTimeTextBox.Value;
    
    P>>if (!myOrder.Valid())
    P>> return;
    P>>// Сохраняется
    P>>myOrder.Save();
    P>>


    AG>а если в таблице миллион записей? Order.Load(orderId); — будет выполнятся довольно долго, может в этом случае все же имеет смыл хранить объект myOrder в сессии, чтобы не вычитывать его из базы при каждом новом Submit странички?



    AG>в целом, как я понял, Ваше решение бОльший упор делает на сохраняемость и масштабируемость экземпляров бизнесс-объектов, а для небольших решений вполне подойдет использование сессии.
    Боишься — не делай, делаешь — не бойся.
    Re[5]: Организация взаимодействия бизнесс-объектов в ASP.NE
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 07.09.06 02:58
    Оценка:
    Здравствуйте, Alex Getman, Вы писали:

    AG>а если в таблице миллион записей? Order.Load(orderId); — будет выполнятся довольно долго,

    Если при миллионе записей загрузка одной из них выполняется довольно долго, то нужно сделать выговор девелоперу, который ее реализовывал.
    Если речь идет об ордере в миллион айтемов (и такие ордера — это часть ТЗ), a при любой загрузке ордера в память поднимаются все айтемы, то нужно делать выговор архитектору.
    AG>может в этом случае все же имеет смыл хранить объект myOrder в сессии, чтобы не вычитывать его из базы при каждом новом Submit странички?
    Это очень-очень-очень вредно. Ребята, распухание сессии — верный способ за DOS-ить сервер на управляемых технологиях. Ни Java ни Net не рассчитаны на производительность в условиях дефицита физической памяти.

    AG>в целом, как я понял, Ваше решение бОльший упор делает на сохраняемость и масштабируемость экземпляров бизнесс-объектов, а для небольших решений вполне подойдет использование сессии.

    Для небольших решений стоимость загрузки не будет такой проблемой, как ты описал выше.
    1.1.4 stable rev. 510
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re: Организация взаимодействия бизнесс-объектов в ASP.NET
    От: GlebZ Россия  
    Дата: 07.09.06 09:14
    Оценка:
    Здравствуйте, Alex Getman, Вы писали:

    AG>Вообщем-то сейчас работает нормально, но меня интересует насколько "правильным" можно назвать такой подход к организации взаимодействия бизнесс-объектов?

    В данном случае не рассмотрен вопрос актуальности данных. Ты будешь поставлять клиенту протухшие данные, в то же время как время протухания может зависеть от многих параметров и индивидуально к каждому объекту. Другие сессии ведь тоже изменяют данные, а сессия у юзера может длиться несколько суток Кроме того, достаточно часто встречаются данные, которые можно закэшировать глобально для всех сессий. Вобщем, юзай Cache индивидуально для каждого объекта(запроса).

    AG>Может быть у кого-то есть опыт альтернативных решений? Имеет ли смыл особо критичные части для призводительности системы переписать для того, чтобы обеспечить сохранение объектов в Cache по ключу уникальному для каждой сессии пользователя?

    Да.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.