У нас на самом деле есть тот же вид проблемы. Мы должны соединить интерфейсом с нашей системой с SAP и безотносительно информации, которую можно найти, самостоятельно не помогает многому. Единственный путь, который работал на данный момент, состоит в том, чтобы найти человека опыта, который помог бы нам бесплатно (такие как наши клиенты, которые выигрывают себя, если они помогают нам взаимосвязать нашу часть с их установкой SAP).
Ведущие курсы, кажется, являются слишком дорогими для предоставления, когда Вы ясно видите, что не изучите много через несколько дней/недели. Другая возможность найма внешних консультантов SAP также не рассмотрена из-за затрат.
я знаю, что они готовы преподавать новым молодым выпускникам ABAP и их систему. Или по крайней мере были готовы, когда они остановили занятость в прошлом году полностью.
С некоторого краткого времени, будучи там (пишущий тезис) я помню, что у них есть обширный внутренний портал с форумами и различным списком. Если у Вас есть друзья, работающие там, можно попросить, чтобы они опубликовали частную рекламу, просящую некоторые частные уроки. Другая опция состоит в том, чтобы забрать студента который, когда то, кто говорит, запустило задание там, но отбросило его после года или около этого. Таким образом, у Вас мог потенциально быть кто-то с некоторым знанием, но еще не стоящий состояние.
Вы можете, например, использовать шаблон стратегии :
Попросите все ваши средства визуализации HTML реализовать общий интерфейс, например IQuestionRenderer
, с имя метода Render (Question)
.
Имейте в своем приложении экземпляр Dictionary
. Заполните его во время инициализации, возможно, на основе файла конфигурации.
Для данного экземпляра вопроса выполните: renderers [question.Type] .Render (question)
Или вы могли бы иметь методы с именами RenderXXX
, где XXX - тип вопроса, и вызывать их с помощью отражения.
Вообще говоря, всякий раз, когда вы видите переключатели на Типе или Перечислении, это означает, что вы можете подставлять объекты как «Тип» - иначе говоря, случай полиморфизма .
На практике это означает, что вы создадите отдельный класс для каждого типа вопроса и переопределите функцию RenderHTML ()
. Каждый объект Question будет отвечать за знание того, какой тип ввода он должен выводить.
Преимущества заключаются в том, что вы удаляете оператор switch, а также создаете хороший объектно-ориентированный код. Недостатком является то, что вы добавляете класс для каждого типа вопроса (в данном случае минимальное влияние).
Почему бы не иметь класс QuestionRenderer
(фактически, это элемент управления), который предоставляет Question
как свойство, которое вы можете установить.
В методе рендеринга вы можете решить, что рендерить в зависимости от типа вопроса.
Это классический случай использования наследования объектов для достижения желаемого. Каждый раз, когда вы видите большой оператор switch, переключающий тип объекта, вам следует рассмотреть некоторую форму подкласса.
Я вижу два подхода, в зависимости от того, насколько «распространены» эти типы вопросов на самом деле и является ли рендеринг единственной разницей между их:
Вариант 1 - Создайте подкласс класса вопроса
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public virtual string RenderHtml();
}
public class MultipleChoiceQuestion
{
public string RenderHtml() {
// render a radio button
}
}
public class MultipleAnswerQuestion
{
public string RenderHtml() {
// render a radio button
}
}
Вариант 2 - Создайте интерфейс визуализации и сделайте это свойством в своем классе вопросов
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public IRenderer Renderer { get; private set; }
}
public interface IRenderer {
void RenderHtml(Question q);
}
public class MultipleChoiceRenderer : IRenderer
{
public string RenderHtml(Question q) {
// render a radio button
}
}
public class MultipleAnswerRenderer: IRenderer
{
public string RenderHtml(Question q) {
// render checkboxes
}
}
В этом случае вы должны создать экземпляр модуля визуализации в вашем конструкторе на основе типа вопроса.
Вариант 1, вероятно, предпочтительнее, если типы вопросов отличаются большим количеством способов, чем отображение. Если визуализация - единственная разница, рассмотрите вариант 2.
Мне не нравится идея, что детали рендеринга находятся в том же классе, что и данные.
Таким образом, одним из вариантов было бы, чтобы ваш метод рендеринга просто генерировал один из набора пользовательские элементы управления, которые обрабатывают фактическую визуализацию HTML.
Другой вариант - иметь отдельный класс QuestionRenderer, который будет иметь различные подклассы для типов вопросов (каждый из которых будет отображать правильный HTML).
Вы можете использовать шаблон стратегии ( Wikipedia ) и фабрику в комбинации.
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
private IQuestionRenderer renderer;
public RenderHtml()
{
if (renderer == null)
{
QuestionRendererFactory.GetRenderer(Type);
}
renderer.Render(this);
}
}
interface IQuestionRenderer
{
public Render(Question question);
}
public QuestionRendererA : IQuestionRenderer
{
public Render(Question question)
{
// Render code for question type A
}
}
public QuestionRendererB : IQuestionRenderer
{
public Render(Question question)
{
// Render code for question type B
}
}
public QuestionRendererFactory
{
public static IQuestionRenderer GetRenderer(QuestionType type)
{
// Create right renderer for question type
}
}
В NHibernate необходимо включить только общедоступные свойства.
Рендеринг определенно является проблемой пользовательского интерфейса, поэтому я бы отделил его от класса Question
и добавил фабрику для изоляции логики переключения ( QuestionControl
базовый класс наследуется от WebControl
и будет содержать большую часть логики рендеринга):
RadioButtonQuestionControl: QuestionControl {
// Contains radio-button rendering logic
}
CheckboxListQuestionControl: QuestionControl {
// Contains checkbox list rendering logic
}
QuestionControlFactory {
public QuestionControl CreateQuestionControl(Question question) {
// Switches on Question.Type to produce the correct control
}
}
Использование:
public void Page_Load(object sender, EventArgs args) {
List<Question> questions = this.repository.GetQuestions();
foreach(Question question in Questions) {
this.Controls.Add(QuestionControlFactory.CreateQuestionControl(question));
// ... Additional wiring etc.
}
}
Я думаю, что вам нужен IUserType, который преобразует свойство из сопоставления гибернации в правильный тип управления через некую фабрику вопросов.
Пример использования IuserType можно найти здесь: NHibernate IUserType
в этом примере конвертирует большой двоичный объект в изображение для использования на стороне клиента, но с той же идеей вы можете создать свою страницу с помощью QuestionType.
Сформулируем очевидное: вы, вероятно, могли бы использовать фабричный метод, чтобы получить экземпляр требуемого визуализированного класса и вызвать его рендеринг, чтобы получить требуемый вывод.
Подход, который я бы выбрал, заключается в создании отдельного Control (или метода HtmlHelper, если вы используете MVC) для каждого визуального стиля, с помощью которого вы хотите, чтобы ваши вопросы отображались. Это разделяет проблемы представления вопроса в виде объекта и его визуально аккуратного представления.
Затем вы можете использовать главный элемент управления (или метод) для выбора правильного метода визуализации на основе типа вопроса
представленный ему экземпляр.
Рекомендуется выделить логику рендеринга в отдельный класс. Вы не хотите, чтобы логика рендеринга была встроена в бизнес-логику вашего приложения.
Я бы создал класс под названием QuestionRenderer, который принимает вопрос, считывает его тип и соответственно выводит рендеринг. Если вы используете ASP.NET, он может выводить веб-элементы управления, или вы можете создать серверный элемент управления, который выводит HTML.