Подтвердить что ты не робот

Объектно-ориентированное программирование стиля для взаимодействия между объектами

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

Сценарий: Человек (Джон) дает Лицу (Бетти) $5.

Возможные решения (псевдокод):

A) John.pays(Betty, 5);
Б) Betty.receives(Иоанн, 5);
C) Bank.transfer(John, Betty, 5);
D)
начать транзакцию:
  John.decrease(5);
  Betty.increase(5);
завершение транзакции:
E) Service.transferMoney(John, Betty, 5);//Служба - это общий объект службы

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

Спасибо.

4b9b3361

Ответ 1

Одна вещь, которую я заметил, это то, что люди, которые являются новыми для ООП, сталкиваются с попыткой сопоставить физический мир с кодом, который они пишут. Вы действительно заботитесь о том, что Джон и Бетти - люди, или вы действительно хотите изобразить банковский счет? Я думаю, что ваш выбор объектов в примере на самом деле затрудняет определение проблемы.

Важными частями этого являются 1) Где поставить логику перемещения денег. 2) Где хранить данные о том, сколько денег имеет каждый человек.

Вам нужно решить, хотите ли вы поговорить о проблеме в контексте человека или клиента банка (может быть лицо, компания или что-то еще). Я предполагаю, что вы говорите о клиенте, потому что предполагая, что это человек будет ограничивать и вводить в заблуждение. Кроме того, Банк - довольно общий термин, это большое кирпичное здание с людьми внутри него или это онлайн-сайт с несколькими разными страницами, которые делают разные вещи. Объект банковского счета может иметь метод (возможно, статический в зависимости от того, как вы решаете хранить свои данные и для чего все, что вы собираетесь использовать для своего объекта), который знает, как перевести из одной учетной записи в другую. Логика перевода не принадлежит Бетти или Джону или банку, она принадлежит к банковскому счету, который может иметь специальную логику, основанную на типе учетной записи, если есть плата или тому подобное. Если вы дадите эту логику банку, вы получите гигантский банковский класс с методами для всего, от того, чтобы сгладить клиента, чтобы иметь дело с деньгами в очень специфических типах счетов. У каждого типа учетной записи у меня есть разные правила для того, как он обрабатывает переводы. Подумайте о временах, когда вы можете показать перевод или депозит в ожидании.

Если вы просто решаете проблему перевода денег, нет необходимости создавать кучу объектов. Основываясь на известных требованиях и предполагаемых будущих требованиях, ниже будет хороший выбор. CheckingAccount.Transfer(johnsAccountNo, bettysAccountNo, количество)

Ответ 2

Можно ли задать вопрос сейчас? Кто контролирует деньги? Определяет ли Джон сумму транзакции, Бетти или какую-то неопределенную третью сторону?

Причина, по которой я спрашиваю, заключается в том, что здесь нет реального права или неправильного ответа, только один, который может быть более гибким или надежным, чем другие. Если это реальная жизненная ситуация, я бы смоделировал транзакцию как нечто, что обе стороны должны договориться до того, как оно поступит, и человек, проводящий деньги (Джон), инициирует его. Что-то вроде ответа C и @Mysterie Man

tx transaction_request = John.WantsToBuyFor(5);    //check if John can
if( Betty.AgreesWith( transaction_request ) )      //check if Betty wants
{
   transaction_request.FinalizeWith(Betty);        //Do it with Betty
}

и функция FinalizeWith выполняет математику

void FinalizeWith(Person party)
{
    requestor.cash -= amount;
    party.cash += amount;
{

Конечно, вы можете добавить некоторое описание того, какой товар покупает Джон.

Ответ 3

Ответ на этот вопрос длинный и сложный, который вы получите в кусках от большого количества людей. Почему только в кусках? Поскольку правильный ответ почти полностью зависит от ваших системных требований.

Одна ловушка, которую вы должны будете удостовериться, что вы не попадаете, однако, этот. Прочтите ответы, которые вы получите здесь. Вы получите много хорошего совета. (Обратите внимание на советы, которые были проголосованы много.) После того, как вы прочитали и поняли их, прочитайте разглашение Стив Йегге ( и понять это!). Это сэкономит вам здравомыслие в долгосрочной перспективе.

Ответ 4

Я бы проголосовал за это:

Почему Джон платит Бетти? Это важный вопрос, поскольку он объясняет, где находится точка входа. Пусть говорят, что Джон должен деньги Бетти, и это день выплаты жалованья.

public class John
{
    public void onPayday()
    {
        Betty.Receive(5.0f);
    }
}

Это, если вы хотите, конечно, пойти с использованием подхода стиля чистого объекта.

Разница здесь в том, что у нас нет внешней процедуры, координирующей взаимодействия между Джоном и Бетти. Вместо этого мы отвечаем на внешние события и выбираем, когда нужно взаимодействовать с Бетти. Этот стиль также приводит к очень простым описаниям желаемой функциональности - например, "в день выплаты жалованья, Джон должен заплатить Бетти".

Это довольно хороший пример того, что означает "Инверсия управления" - объекты взаимодействуют друг с другом, а не манипулируются какой-либо внешней процедурой. Это также пример Tell, Do not Ask, поскольку объекты рассказывают друг другу вещи (Джону сказали, что это зарплата, Джон говорит Бетти принять 5 долларов).

Ответ 5

Здесь есть несколько альтернативных решений. Например,

Betty.Receieves(John.Gives(5))

Это предполагает, что функция Gives возвращает указанную сумму.

tx = CashTransaction(John, Betty);
tx.Transfer(5);

Предполагается, что первым prameter является Payor, а второй - Payee, затем вы можете выполнять несколько транзакций без создания новых объектов.

Вещи можно смоделировать несколькими способами. Вы должны выбрать тот, который наиболее похож на то, что вы пытаетесь моделировать.

Ответ 6

Существует одно свойство чистого ООП, которое может помочь с примером, который легко проходит под радаром, но модель object-capability делает явно и сосредоточен. Связанный документ ( "От объектов к возможностям" (FOtC)) подробно рассматривается в теме, но (вкратце) точка возможностей заключается в том, что способность объекта влиять на его мир ограничена объектами, на которые он ссылается. Сначала это может показаться незначительным, но очень важно, когда дело доходит до защиты доступа и влияет на то, какие методы класса доступны в методах других классов.

Вариант A) дает доступ учетной записи John к учетной записи Betty, в то время как опция B) дает Бетти доступ к учетной записи John; не желательно. С вариантом C), доступ к учетной записи опосредуется Банком, поэтому только банки могут украсть или подделать деньги. Вариант D) отличается от остальных трех: другие показывают отправленное сообщение, но не реализацию, а D) - это реализация метода, которая не показывает, какое сообщение оно обрабатывает, и какой класс он обрабатывает. D) может быть легко реализована для любого из первых трех вариантов.

FOtC имеет начало решения, которое включает в себя несколько других классов:

  • герметики и разборщики,
  • кошельки, которые немного напоминают счета в том, что они содержат деньги, но необязательно имеют владельца.
  • mints, которые являются единственными вещами, которые могут создавать кошельки с положительными балансами.

Монетный двор имеет пару уплотнителя/отцепления, которую он наделяет кошельком всякий раз, когда мята создает его. Кошельки контролируют изменения баланса; они используют герметик при уменьшении баланса, а второй - для перехода от одного кошелька к другому. Кошельки могут порождать пустые кошельки. Из-за использования герметиков и вскрытий кошелек работает только с другими кошельками, созданными одним и тем же мятой. Кто-то не может писать свой кошелек, чтобы подделывать деньги; только объект с доступом к монетному двору может создавать деньги. Подделка предотвращается путем ограничения доступа к монетным дворам.

Любой, у кого есть доступ к кошельку, может инициировать транзакцию путем нереста пустого кошелька и перевода денег с первого кошелька в него. Затем временный кошелек может быть отправлен получателю, который может переводить деньги из временного кошелька в другой кошелек, который ему принадлежит. Воровство предотвращается путем ограничения доступа к кошелькам. Например, банк держит кошельки от имени клиентов на счетах. Поскольку у банка есть доступ только к кошелькам своих счетов клиентов и временным кошелькам, только клиентский банк может украсть у клиента (хотя обратите внимание, что при передаче между банковскими счетами могут быть жертвами двух клиентов, следовательно, два потенциальных воры).

В этой системе отсутствуют некоторые важные детали, такие как органы денежно-кредитного регулирования (которые содержат ссылки на один или несколько монетных дворов) для создания денег.

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

Ответ 7

Если вы действительно хотите получить OOPy, попробуйте следующее

Person       Betty,John;
CashTransfer PocketMoney;
PocketMoney.from   = John;
PocketMoney.to     = Betty;
PocketMoney.amount = 20.00;
PocketMoney.transfer();

Точка OOP не должна делать код более похожим на письменный язык, а иметь объекты с различными методами и параметрами, чтобы сделать код более читаемым.

Итак, из приведенного выше кода вы можете видеть, что Джон дает Бетти 20 долларов в карманных деньгах. Код имеет смысл, что позволяет упростить читаемость кода, а также понятность.

Ответ 8

Мой голос: C. Где C делает то, что делает D (например, не теряет деньги и т.д.).

В этом небольшом примере "банк" - это совершенно правильная организация, которая знает, сколько денег у Джона и Бетти. Ни Джон, ни Бетти не смогут лгать банку.

Не бойтесь инвертировать (или нет) логику в программе "OO", как это требуется для ситуации.

Ответ 9

Вы должны моделировать в соответствии с вашим доменом. Вариант C выглядит лучшим выбором, поскольку он будет разделять логику транзакций в классе Bank\Service.

Ответ 10

Это вопрос, который я часто борюсь с собой как начинающий программист. Я согласен с тем, что "С" кажется лучшим выбором. В чем-то подобном я считаю, что лучше использовать "нейтральную" сущность, такую ​​как "банк". Это фактически моделирует большинство реальных транзакций, имеющих важное значение, поскольку в большинстве транзакций импорта используются чеки и/или кредит (нейтральная сторонняя сторона).

Ответ 11

Будучи новым для ООП и, наконец, используя некоторый ООП, я бы сказал, что он должен быть A и B.

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

Создан класс Person, и вы добавляете методы в класс двумя способами: отправкой и получением. Он также должен иметь открытый баланс var, чтобы отслеживать их балансы.

Вы создаете два объекта Person: Betty и John. Используйте методы соответственно. Как и John.sends(Бетти, 5). Это должно создать Betty и обновить баланс Betty.

Что делать, если они хотят использовать банк? Добавьте другой метод, скажем... Передача (acct), что бы это ни было.

Что бы я подумал.