Search
Write a publication
Pull to refresh

Comments 12

UFO landed and left these words here
Да, это редкая ситуация. Но когда все же возникает — решать как-то надо
Следующий после вас разработчик будет очень грустно перебирать form.Item1...Item42 в поисках IYetAnotherButtonPropertyInterface.
Переносить логику раскраски в формы. Передавать из контроллера (презентера) только данные/состояние. Делать разделение интерфейсов на уровне форм, если с одной формой действительно работает несколько контроллеров. Не открывать наружу элементы в виде свойств. Делать у формы (вида) методы HighlightWelcomeButton, SetWelcomeText и событие WelcomeClicked. У вас практически Model-View-Presenter, но с нарушением инкапсуляции вида. А нарушение инкапсуляции приводит к высокой связности, которую вы как раз пытаетесь побороть.
Немного опечатался, Связности -> Связанности, которая Coupling.
Да, про MVP я в курсе. Но задача применима не только к UI (про кнопку с кликом и цветом я написал только для примера).
Ваше решение, как минимум, оригинально :) Хотя обращения через .Item1, .Item2 и т.п. выглядят некрасиво. Использовать такое тоже достаточно неинтуитивно.

Пришло на ум еще вот такое решение:

class BaseButton { }

interface IClickable { event Action Click; }

interface IColored { Color Color { get; set; } }

interface ITextContaining { string Text { get; set; } }

class CoolButton : BaseButton, IClickable, IColored, ITextContaining
{
    // реализует все интерфейсы
}

class MyForm
{
    private BaseButton button;

    public BaseButton Button
    {
        get { return button; }

        set
        {
            if(!(value is IColored || !(value is IClickable)))
            {
                throw new ArgumentException("Button object must be clickable and colored");
            }

            button = value;
        }
    }

    public Action ButtonClick
    {
        get
        {
            return (button as IClickable).Click;
        }
    }

    // [...]
}


Ну, а вообще, я согласен с первым комментатором. Такие извороты обычно говорят об ошибке проектирования. Я бы, все же, постарался обойтись проектированием через интерфейсы и выделению для каждого конкретного случая нужного интерфейса.
Всё так. В любом случае абстрагирование «по-взрослому» — только через интерфейсы. Наследование — это лишь удобный способ устранить дублирование кода. Поэтому хорошо спроектированный код часто содержит кучу небольших интерфейсов.
Скажите, а пример с кнопкой — это реальный пример? Потому что в нем явно можно обойтись нормальным наследованием — например:
class BaseButton : IClickable { ... }

class ColorButton: BaseButton, IColored { ... }

class TextColoredButton ...

Да и вообще, где вы видели столько разных контролов — и кнопка текстовая, и цветная, и цветная текстовая некликабельная, и цветная текстовая кликабельная, и еще 10 штук других сочетаний… Обычно ведь этих кнопок 2-3 разных вида. И в классах-формах можно использовать именно эти 2-3 конкретных класса.
У вас есть какой-нибудь другой пример, где это может понадобиться?
Про кнопку — это просто пример. У меня была такая ситуация в коде с сервисами и провайдерами данных — они содержали кучу свойств/методов, и я их пытался расчленять на более простые. Напрмер, был провайдер SQL-БД, который имел сотни методов для доступа к разным таблицам — пришлось выделить интерфейсы для работы с разными сущностями (каждый интерфейс содержал десятки методов, получилось несколько таких интерфейсов). Но потом мне пришлось передавать эти интерфейсы в слой бизнес логики путем их перечисления, а это как-то не очень красиво.
И в этом случае можно было найти более очевидное и понятное другому человеку решение… Лучше пусть будет «Не очень красиво» чем неочевидно и несопровождаемо. Красивый код не тот, который выглядит ровненько.
Sign up to leave a comment.

Articles