Вопрос о дизайне: набирает ли телефон PhoneNumber или PhoneNumber набирает себя на телефоне?

Это переиздано из того, что я разместил на DDD Yahoo! группа.

При прочих равных вы пишете phone.dial(phoneNumber) или phoneNumber.dialOn(phone)? Имейте в виду возможные будущие требования (номера счетов в дополнение к номерам телефонов, калькуляторы в дополнение к телефонам).

Этот выбор иллюстрирует, как идиомы Информационного эксперта, Принципа единой ответственности и "Не спрашивай" расходятся друг с другом.

phoneNumber.dialOn (phone) предпочитает Information Expert и Tell Not Ask, а phone.dial(phoneNumber) предпочитает принцип единой ответственности.

Если вы знакомы с работой Кена Пью в Prefactoring, это загадка Spreadsheet; Вы добавляете строки или столбцы?

13 ответов

Решение

Выбор типа столбца или объекта строки в методе dial не меняет масштаб программы.

Метод dial будет представлять собой последовательность методов строк и столбцов. Вы должны спросить, от чего зависят эти методы.

Если последовательность методов строки не зависит от точного знания того, какой объект столбца задействован (но зависит от того, какой конкретный объект строки задействован) и наоборот для последовательности методов столбца, то проблема масштабируется как m + n (m = количество строк, n = количество столбцов). Когда вы создаете новую строку, она фактически не спасает вас от работы, если для метода столбца был назначен метод dial. Вы все еще должны указать уникальную последовательность методов строки для использования в 'dial' где-нибудь!

Если, однако, скажем, что последовательность методов столбцов внутри "dial" даже не зависит от того, какой объект столбца задействован (они используют одну "общую" последовательность методов столбцов), то проблема просто масштабируется как m. На самом деле не имеет значения, если вы назначили метод "dial" для объектов столбца, программа по-прежнему масштабируется как m; по существу, не требуется никакой работы для создания нового метода набора номера при добавлении еще одного объекта столбца, и у вас явно есть возможность абстрагировать все эти методы набора номера в один общий метод набора номера.

phone.dial()потому что это телефон, который делает набор номера.

Actor.Verb (входы) -> выходы.

Meh - User.Dial(номер). Телефон не имеет смысла в данном контексте. SOL (говорите вслух) - хороший способ обдумать это (помимо идиом и принципов):

Телефоны имеют циферблат. Они не могут набрать себя. Номера телефонов являются цифрами. Пользователи набирают номера телефонов на наборе номера.

Вопрос предполагает контекст ответа и, следовательно, создает ложную дилемму

"загадка электронной таблицы" в данном примере является ложной дихотомией: строки и столбцы являются уровнем представления, а не обязательно уровнем данных. Комментарии ниже говорят мне, что я неправильно понял аналогию, но я так не думаю - говоря "если это строка или столбец, который с большей вероятностью изменится", вынуждает делать ненужный выбор в проблемном пространстве - они оба с одинаковой вероятностью может измениться. И в этом конкретном примере это приводит к выбору неправильной [да неверной] парадигмы для решения. Набор номера телефона - это то, как старые механические устройства инициировали соединение с другим старым механическим устройством; вряд ли это удачная аналогия для современной телефонии. И если предположить, что есть "пользователь", который инициирует вызов, просто перемещает проблему - хотя он перемещает ее в правильном направлении, то есть от модели телефона с поворотным кругом;-)

Если вы посмотрите на то, как работает протокол TAPI [извините за опечатку раньше, это TAPI, а не ATAPI!], То есть контроллер вызовов - эквивалент "пользователя", который, я полагаю, в некотором смысле - который управляет соединениями между устройствами. Одно устройство не вызывает другое, контроллер вызовов соединяет устройства. Поэтому приведенный ниже пример по-прежнему верен It might be more correct to use a CallController object instead of a generic Connection, but the analogy should be clear enough as is.

In this example, a phone is a device with an address aka a 'phone number'. The 'dial' operator establishes a connection between the two devices. Итак, ответ:

Phone p1 = new Phone(phoneNumber1);
Phone p2 = new Phone(phoneNumber2);
Connection conn = new Connection(p1,p2);
conn.Open();
//...talk
conn.Close();

this will support multi-party calls as well, by overloading Connection to include a list of devices or other connections, eg

Connection confCall = new Connection(p1,p2,p3,p4,p5,p6);
confCall.Open();

Connection joinCall = new Connection(confCall,p7,p8,conn);
joinCall.Open();

look at the TAPI protocol for more examples

Ни. Пользователь набирает номер телефона на телефоне.

A: phone.dial(номер телефона)

PhoneNumber тупой и является только набором данных. Когда происходит "набор номера", должен ли объект PhoneNumber знать, как набирать номер? Есть много состояний для отслеживания, например:

  • Телефон уже на другом звонке? (если да / нет, что делать?)
  • Что произойдет, если метод набора изменится? (глобальный роуминг, другой оператор и т. д.)
  • Кроме того, как насчет области? При совершении вызова телефонный номер необходимо добавить в список последних исходящих вызовов.

Если ваш объект PhoneNumber должен знать все это, он не СУХОЙ, и ваш код будет менее переносимым и с большей вероятностью сломается.

Я бы сказал, что у Стивена А. Лоу это есть. Это должно быть сделано с помощью объекта типа Controller для обработки различных состояний и т. Д. Держите объект PhoneNumber в тупом состоянии и передавайте смарт-сигналы посреднику, который должен беспокоиться о сохранении гудения телефона.

Понятно, телефон. Набор (номер)

Очевидно, что интерфейс PhoneUserInterface, реализацию которого вы можете получить из метода PhoneUserFactory.CreatePhoneUser(), имеет метод dial(Phone, Number), который можно использовать для набора номера телефона.

РЕДАКТИРОВАТЬ: Отвечая на комментарий. Ни. На телефоне должна быть кнопка Press () или что-то в этом роде. Пользователь вводит цифры / символы номера телефона через этот интерфейс.

Если вы пишете OO, то вы начинаете с базового объекта, который не является номером, номер идет в телефон, поэтому phone.dial() таким образом вы также можете phone.answer() phone.disconnect() phone.powerOFF и т. д.

Другой способ взглянуть на это - телефон набирает номер или телефон набирает номер?

Я не уверен, как это связано с загадкой электронной таблицы. Ожидаете ли вы в будущем использовать телефоны для набора номеров счетов? Использовать номера телефонов на калькуляторах? Ваш пример "готовности к будущим требованиям" не очень хорош...

Кроме того, вы используете глагол "циферблат". Конечно, я мог бы представить "набор" номера счета на телефоне. (Хотя это большой отрезок.) Но если этот телефонный номер будет использоваться на калькуляторе, вы бы назвали действие "набор номера"? Если имя функции изменяется в зависимости от типа передаваемого параметра, возникает ошибка проектирования.

В типичном дизайне ОО объекты получают отправленные сообщения, содержащие данные, а не наоборот.

Не будь здесь отрицательным, но такие вопросы очень академичны. Это полностью зависит от приложения. Я думаю, что очень хорошие причины делать это так или иначе, и я видел слишком много хороших программистов увязнуть в таком роде спорных деталей дизайна.

У меня не было бы номера телефона как класса вообще, потому что он не имеет никакого поведения, это просто элемент данных.

phone.dial() +1.

Что такое вариант состояния или поведения PhoneNumber? Единственное, что приходит на ум, - это "правила набора номера" (наберите код страны, если он снаружи, наберите "9", чтобы выйти на внешнюю линию и т. Д.). Этот контекст, кажется, хорошо подходит для телефона.

Если ваша объектная модель не требует дисперсии - число - это просто последовательность цифр, "циферблат" - это просто foreach (цифра в телефонном номере) {нажмите (цифра); } Я с Робом Конери: Мех.

Другие вопросы по тегам