Когда я думаю о машине для кока-колы, я вижу кнопку для каждого типа напитка в машине, но не кнопки для разных сумм денег.Возможно, вы имеете в виду, что кокс стоит 50 центов, поэтому при нажатии на кнопку кокса мне нужно заряжать 50 центов.
Кнопки и обработчики событий
Когда вы нажимаете кнопку на экранеон генерирует событие клика .Вам нужно написать метод, чтобы ответить на этот клик.Любой метод, который мы используем для ответа на событие (вообще говоря), называется обработчиком события .Вы должны сообщить своей программе, какие кнопки идут с какими обработчиками событий.Мы называем это регистрация обработчика события
По соглашению, если ваша кнопка называется CokeButton, то обработчик события, связанный с этой конкретной кнопкой, будет называться CokeButton_ClickHandler.Или что-то в этом роде.
Общие советы
Подумайте о том, что вы моделируете, и определите вещи в коде, чтобы они отражали реальный мир. вещи в вашей модели обычно заканчиваются как классы, свойства класса и поля класса.То, что эти вещи делают, обычно заканчиваются методами в соответствующем классе.Затем вы думаете о том, как эти вещи взаимодействуют.
Вам не нужно выяснять всего о коксовой машине, прежде чем вы начнете писать код.И вы должны писать маленькие кусочки за раз, проверять их, а затем опираться на то, что вы проверяли.Не пишите кучу сложного кода, а затем тестируйте.Вы будете вращаться кругами, преследуя свой хвост.Напишите немного, немного попробуйте, повторите. Услышь меня сейчас и поверь мне позже;Пиши немного, тестируй немного, повторяй. Прислушайся к этому совету сейчас и навсегда.
Так вот как я могу подумать о кока-коле.Сначала есть сама кока-машина.
public class CokeMachine {}
Коксовая машина имеет слот для денег, слот для возврата и кнопки для напитков.Я не могу положить деньги в слот, так что я бы сказал, что наберу текст в поле.Тогда я нажму на кнопку, и кокс раздастся.Я чувствую, что определил достаточно модели, чтобы начать.Есть много других вещей в кока-машине, но я не буду беспокоиться о них прямо сейчас.
Но мне нужно знать, сколько стоит каждый напиток.
Ладно, хорошо.тогда должны быть поля "CokeCost", "7UpCost" и т. д.Так определите их!Мы выясним, как и где их использовать, по мере продвижения.
public class CokeMachine {
Button Coke;
Button 7Up;
Button RootBeer;
TextBox MoneySlot;
double CokeCost = .75;
double 7UpCost = .65;
}
Я сказал, что кнопкам нужны обработчики, поэтому мы можем написать как минимум несколько оболочек кода.Я ожидаю, что все они будут работать одинаково, поэтому сейчас я сосредоточусь на одном.Обратите внимание, что когда я пишу код, я осознаю другие вещи, с которыми нужно иметь дело.Я добавлю комментарии, вызовы методов, которые еще не существуют, и т. Д.
public class CokeMachine {
Button Coke;
Button 7Up;
Button RootBeer;
TextBox MoneySlot;
double CokeCost = .75;
double 7UpCost = .65;
// "wiring up" the coke button click event to it's handler.
// We do this in C# by declaring an new EventHandler object (a .NET framework supplied class)
// and we pass in the name of our method as a parameter.
// This new EventHandler is *added* to the button's click event.
// An event can have multiple handlers, that's why we do "+="
// instead of just "=". Otherwise we would have accidentally "unhooked" any
// previously registered handlers.
Coke.Click += new EventHandler(Coke_ClickHandler);
// this is the .NET event handler method signature.
Public void Coke_ClickHandler (object sender, EventArgs args){
if (MoneySlot.Value >= CokeCost) {
DispenseDrink();
// How do I handle returning change? Maybe DispenseDrink() can do that.
}else {
// tell customer to put in more money
}
}
private void DispenseDrink() {
// An empty method is enough to get it to compile so for now that's fine.
// I need to test the Coke_EventHandler logic that I've written so far.
}
}
Теперь мне нужно проверить то, что я написал до сих пор.После этого мне нужно решить, на чем сосредоточиться дальше.Но поймите, что когда вы пишете новый код, который зависит от уже написанного кода, если этот существующий код не был протестирован - и теперь вы видите ошибки, вы только что сделали это намного сложнее для себя.Вы могли бы проверить, когда код проще.Теперь есть еще кое-что, более сложное, и его будет сложнее отлаживать и исправлять.
Предложения, Часть II
На риск все испортится, я предлагаю этоДалее к моему первоначальному ответу:
Вы можете видеть, что каждая кнопка напитка делает одно и то же, и, учитывая приведенный выше код, мы будем писать одну и ту же логику снова и снова для каждой кнопки.Если что-то должно измениться, мы должны изменить это везде.
Дополнительные общие рекомендации
Одна объектно-ориентированная эвристика прогамминга инкапсулирует то, что остается прежним .Вы всегда должны быть в поисках мест, где вещи могут быть кандидатами в общий код.
Я хочу подчеркнуть, что это обычное поведение кнопок не было для меня сразу очевидным. Только после того, как я написал приведенный выше код, я подумал, что все мои обработчики кнопок для напитков будут выглядеть одинаково, и я понял, что на реальной машине для напитков они действительно ведут себя одинаково. Мой смысл в коде сказал, что это хорошо, когда код отражает идентифицируемое поведение вашей реальной вещи (каламбур!).
Рефакторинг
На самом деле это технический термин, который означает переработку существующего кода, чтобы сделать его более гибким, многократно используемым, читаемым и т. Д. Одним словом ремонтопригоден.
Рефакторинг должен постоянно находиться в ваших мыслительных процессах. Но убедитесь, что у вас есть законная причина для каких-либо изменений. Изменение кода является нормальной, неотъемлемой частью разработки программного обеспечения.
Давайте рефакторинг путем извлечения метода
Public void Coke_ClickHandler (object sender, EventArgs args){
PurchaseDrink("Coke", CokeCost);
}
// now we have a method that stands out and says THIS is how it works
// and a single point of change, rather than ump-teen button handlers.
private PurchaseDrink (string whatKind, double cost) {
// all I did so far is move the code and change "Cokecost" to "cost"
// Now I'm beginning to think I may need to pass "whatKind" to
// DispenseDrink() - but first I need to test the changes I've
// made at this level.
// ***** and since I already tested the code when I 1st wrote it,
// this refactoring will be easier & quicker to test.. GET IT??!! ******
if (MoneySlot.Value >= cost) {
DispenseDrink();
// How do I handle returning change? Maybe DispenseDrink() can do that.
}else {
// tell customer to put in more money
}
}
private void DispenseDrink() {
// An empty method is enough to get it to compile so for now that's fine.
// I need to test the Coke_EventHandler logic that I've written so far.
}
Перечисления
Я ненавижу использовать строки, как я использовал "Кокс" выше. Опечатки и регистр (то есть верхний / нижний) могут вызвать проблемы, которые Visual Studio не поймает. Когда у меня есть ограниченный список вещей - виды напитков - я действительно люблю использовать перечисления. Они обнаруживаются в интеллектуальном смысле, и я могу использовать их в выражениях переключателя (и исследовать идею «безопасного типа»). И что мне действительно нравится, так это то, что они абсолютно определяют в одном месте все типы напитков, о которых знает наша программа. Это как документация!