ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 11.12.2025
Просмотров: 3272
Скачиваний: 1
Э то хорошее начало для выполнения рефакторинга. Кроме того, если вы внимател рассмотрите часть ввода начальной информации, то увидите, что код для ввода
вклада,
процентной ставки и
срока практически один и тот же. Это наблюдение дает еще одну точку для рефакторинга.
Все перечисленное позволяет выполнить рефакторинг программы Calcl l a t e l n t e r e s t T a b l e и создать программу C a l c u l a t e l n t e r e s t T a b l e W i t h F u n c t i o n s .
/ / C a l c u l a t e I n t e r e s t T a b l e W i t h F u n c t i o n s
// Генерация таблицы роста вклада по тому же алгоритму, что
//и ранее рассматривавшихся программах, однако в этой
//программе работа распределена между несколькими
//функциями.
u s i n g S y s t e m ;
n a m e s p a c e |
C a l c u l a t e I n t e r e s t T a b l e W i t h F u n c t i o n s |
{ |
|
p u b l i c c l a s s P r o g r a m |
|
{ |
|
p u b l i c |
s t a t i c v o i d M a i n ( s t r i n g [ ] a r g s ) |
{
//Раздел 1 - ввод данных, необходимых для создания
//таблицы
d e c i m a l m P r i n c i p a l = 0 ; d e c i m a l m l n t e r e s t = 0,- d e c i m a l m D u r a t i o n = 0 ;
I n p u t l n t e r e s t D a t a ( r e f m P r i n c i p a l , r e f m l n t e r e s t , r e f m D u r a t i o n ) ;
//Раздел 2 - проверка введенных данных путем вывода
//их пользователю на экран
C o n s o l e . W r i t e L i n e ( ) ; |
/ / s k i p a . l i n e |
|
C o n s o l e . W r i t e L i n e ( " В к л а д |
= " + |
|
m P r i n c i p a l ) ; |
|
|
C o n s o l e . W r i t e L i n e ( " П р о ц е н т н а я ставка = " +
m l n t e r e s t + |
" % " ) ; |
C o n s o l e . W r i t e L i n e ( " С р о к |
= " + |
m D u r a t i o n + . " лет");
C o n s o l e . W r i t e L i n e ( ) ;
//Раздел 3 - и, наконец, вывод таблицы вкладов по
//годам
O u t p u t l n t e r e s t T a b l e ( m P r i n c i p a l , m l n t e r e s t , m D u r a t i o n ) ;
// Ожидаем подтверждения |
пользователя |
C o n s o l e . W r i t e L i n e ( " Н а ж м и т е |
< E n t e r > для " + |
744 |
Часть III. Объектно-основанное программирован |
" з а в е р ш е н и я п р о г р а м м ы . . . " ) ;
C o n s o l e . R e a d ( ) ;
}
/ / I n p u t l n t e r e s t D a t a - к л а в и а т у р н ы й в в о д в к л а д а , / / п р о ц е н т н о й с т а в к и и с р о к а д л я р а с ч е т а т а б л и ц ы
//Эта функция реализует раздел 1, разбивая его на три
//компонента
p u b l i c |
s t a t i c |
v o i d |
I n p u t l n t e r e s t D a t a ( r e f |
|
r e f |
|
r e f |
d e c i m a l d e c i m a l d e c i m a l
m P r i n c i p a l , m l n t e r e s t , m D u r a t i o n )
{
/ / l a П о л у ч е н и е в к л а д а |
|
m P r i n c i p a l |
= I n p u t P o s i t i v e D e c i m a l ( " в к л а д " ) ; |
/ / 1 6 П о л у ч е н и е п р о ц е н т н о й с т а в к и |
|
m l n t e r e s t = |
I n p u t P o s i t i v e D e c i m a l ( " п р о ц е н т н а я с т а в к а " ) ; |
// 1в П о л у ч е н и е с р о к а
m D u r a t i o n = I n p u t P o s i t i v e D e c i m a l ( " с р о к " ) ;
}
/ / I n p u t P o s i t i v e D e c i m a l - в о з в р а щ а е т п о л о ж и т е л ь н о е ч и с л о / / т и п а d e c i m a l с к л а в и а т у р ы .
/ / В ы п о л н я е т с я т о л ь к о о д н а п р о в е р к а - н а / / н е о т р и ц а т е л ь н о с т ь в в е д е н н о г о з н а ч е н и я . p u b l i c s t a t i c
d e c i m a l I n p u t P o s i t i v e D e c i m a l ( s t r i n g s P r o m p t )
{
/ / Ц и к л в ы п о л н я е т с я , п о к а н е б у д е т в в е д е н о в е р н о е / / з н а ч е н и е
w h i l e ( t r u e )
{
/ / П р и г л а ш е н и е д л я в в о д а
C o n s o l e . W r i t e ( " В в е д и т е " + s P r o m p t + " : " ) ;
/ / П о л у ч е н и е з н а ч е н и я т и п а d e c i m a l с к л а в и а т у р ы s t r i n g s l n p u t = C o n s o l e . R e a d L i n e ( ) ;
d e c i m a l m V a l u e = C o n v e r t . T o D e c i m a l ( s l n p u t ) ;
/ / В ы х о д и з ц и к л а п р и в в о д е к о р р е к т н о г о з н а ч е н и я i f ( m V a l u e > = 0 )
{
/ / В о з в р а т в в е д е н н о г о з н а ч е н и я r e t u r n m V a l u e ;
}
/ / В п р о т и в н о м с л у ч а е г е н е р и р у е т с я и в ы в о д и т с я / / с о о б щ е н и е о б о ш и б к е
C o n s o l e . W r i t e L i n e ( s P r o m p t +
Глава 7. Функции функций |
145 |
" н е м о ж е т и м е т ь о т р и ц а т е л ь н о е з н а ч е н и е " ) ; C o n s o l e . W r i t e L i n e ( " П о п р о б у й т е е щ е р а з " ) ;
C o n s o l e . W r i t e L i n e ( ) ;
}
}
/ / O u t p u t l n t e r e s t T a b l e / / п р о ц е н т н о й с т а в к и и / / э к р а н т а б л и ц у р о с т а
- д л я з а д а н н ы х з н а ч е н и й в к л а д а , с р о к а г е н е р и р у е т и в ы в о д и т н а в к л а д а
// Реализация раздела 3 основной программы
p u b l i c s t a t i c
v o i d O u t p u t l n t e r e s t T a b l e ( d e c i m a l d e c i m a l d e c i m a l
m P r i n c i p a l , m l n t e r e s t , m D u r a t i o n )
{
f o r ( i n t n Y e a r = 1 ; n Y e a r < = m D u r a t i o n ; n Y e a r + + )
{
/ / В ы ч и с л е н и е н а ч и с л е н н ы х п р о ц е н т о в d e c i m a l m l n t e r e s t P a i d ;
m l n t e r e s t P a i d = m P r i n c i p a l * ( m l n t e r e s t / 1 0 0 ) ;
/ / В ы ч и с л е н и е з н а ч е н и я н о в о г о в к л а д а п у т е м / / д о б а в л е н и я н а ч и с л е н н ы х п р о ц е н т о в к о с н о в н о м у / / в к л а д у
m P r i n c i p a l = m P r i n c i p a l + m l n t e r e s t P a i d ;
/ / О к р у г л е н и е в к л а д а д о к о п е е к
m P r i n c i p a l = d e c i m a l . R o u n d ( m P r i n c i p a l , 2 ) ;
/ / В ы в о д р е з у л ь т а т а
C o n s o l e . W r i t e L i n e ( n Y e a r + " - " + m P r i n c i p a l ) ;
}
}
}
}
Раздел M a i n () разделен на три очевидные части, каждая из которых выделена и ментарием с полужирным шрифтом. Кроме того, первая часть, в свою очередь, подела на три подраздела — 1а, 1би 1в.
Вам не следует пытаться выделять в своих исходных текстах комментарии лужирным шрифтом или номерами разделов. Исходный текст реальной про граммы и без того сложная и запутанная штука, чтобы вносить в него искуст венные усложнения. На практике для понимания достаточно ясных и информ тивных имен функций, указывающих их предназначение.
В первой части для ввода значений трех переменных, необходимых для работы про граммы ( m P r i n c i p a l , m l n t e r e s t и м m D u r a t i o n ) , вызывается функция I n p u t l n t e r e s t D a t a ( ) . Во второй части полученные значения выводятся на экран так же, и и в предыдущих версиях программы. Последняя часть строит и выводит на экран таблица цу вкладов с помощью функции O u t p u t l n t e r e s t T a b l e ( ) .
Начнем с конца, с функции O u t p u t l n t e r e s t T a b l e ( ) . В ней содержится цш в котором выполняется вычисление начисленных процентов — в точности так же, ю
146 |
Часть III. Объектно-основанное программирован» |
это делалось в программе C a l c u l a t e l n t e r e s t T a b l e в главе 5, "Управление потоком выполнения". Преимущество данной версии заключается в том, что при разработке этой части кода не нужно сосредотачиваться на деталях ввода и верификации данных. При написании этой функции следует просто думать о том, как вычислить и вывести таблицу для уже полученных значений. После выполнения функции управление вернется в стро ку, следующую за вызовом функции O u t p u t l n t e r e s t T a b l e ( ) .
O u t p u t l n t e r e s t T a b l e ! ) — хороший повод для того, чтобы воспользо ваться новым меню Refactoring в Visual Studio 2005. Для этого надо выполнить следующие действия.
1.Воспользоваться в качестве стартовой точки примером CalculatelnterestTableMoreForgiving из главы 5, "Управление потоком выполнения", вы брав исходный текст от объявления переменной nYear до конца цикла while:
i n t n Y e a r = |
0 ; |
/ / П е р е м е н н а я ц и к л а |
w h i l e ( n Y e a r |
< = n D u r a t i o n ) |
/ / и в е с ь ц и к л w h i l e |
{ |
|
|
//...
}
2.Выбрать команду меню Refactor^Extract Method.
3.В диалоговом окне Extract Method ввести O u t p u t l n t e r e s t T a b l e , затем
просмотреть поле Preview Method Signature и щелкнуть на кнопке ОК.
Обратите внимание, что предложенная "сигнатура" нового "метода" начинается с ключевых слов p r i v a t e s t a t i c и включает m P r i n c i p a l , m l n t e r e s t и n D u r a t i o n в круглых скобках. О ключевом слове p r i v a t e , как альтернативе p u b l i c , будет рассказано в главе 11, "Классы". Пока же вы можете при желании сделать эту функцию p u b l i c .
Результат такого рефакторинга заключается в следующем.
/ Ниже функции M a i n ( ) p u t l n t e r e s t T a b l e
добавляется новая p r i v a t e s t a t i c функция O u t ( ) .
/Там, где в функции M a i n () находился выбранный код, появляется следующая строка:
m P r i n c i p a l = O u t p u t l n t e r e s t T a b l e ( m P r i n c i p a l ,
m l n t e r e s t , n D u r a t i o n ) ;
Точно такой же подход "разделяй и властвуй" применим и для функции I n p u t l n t e r e s t D a t a ( ) . Однако в этом случае требуется более сложный рефакторинг, так что я выполнил его вручную и все его этапы здесь не показаны. Все же искусство рефакто ринга выходит за рамки настоящей книги.
В функции I n p u t l n t e r e s t D a t a () вы сосредотачиваетесь только на вводе трех зна чений типа d e c i m a l . В данном случае, несмотря на три различные переменные, действия по их вводу оказываются идентичны и могут быть размещены в функции I n p u t P o s i tiveDecimal ( ) , которая одинаково применима как для ввода вклада, так и для ввода процентной ставки и срока, для которого выполняется расчет. Заметьте, как три цикла while в исходной программе превратились в один в теле функции I n p u t P o s i t i v e D e c i m a l ( ) . Тем самым устранено дублирование кода, которое всегда нежелательно.
[пава 7. Функции функций |
147 |
Внесение в программу модификаций, делающих ее понятнее и проще, не га няя при этом ее функциональность и внешнее поведение, называется рефак рингом. Большое количество информации о нем можно найти на Web-ca w w w . r e f a c t o r i n g . c o m .
Функция I n p u t P o s i t i v e D e c i m a l () выводит приглашение и ожидает ввода по] зователя. Если введенное пользователем значение неотрицательно, она возвращает вызвавшей ее функции. Если же введенное значение отрицательно, функция выводит! общение об ошибке и повторяет цикл ввода.
С точки зрения пользователя получается та же программа, что и раньше (в глав "Управление потоком выполнения"), поскольку работает она в точности так же:
В в е д и т е |
в к л а д : 1 0 0 |
В в е д и т е |
п р о ц е н т н у ю с т а в к у : - 1 0 |
П р о ц е н т н а я с т а в к а н е м о ж е т б ы т ь о т р и ц а т е л ь н а |
|
П о п р о б у й т е е щ е р а з |
|
В в е д и т е |
п р о ц е н т н у ю с т а в к у : 1 0 |
В в е д и т е |
с р о к : 1 0 |
В к л а д |
= |
10 0 |
П р о ц е н т н а я |
с т а в к а = |
10% |
С р о к |
= |
1 0 л е т |
1 - 1 1 0 . 0
2 - 1 2 1 . 0 0
3 - 1 3 3 . 1 0
4 - 1 4 6 . 4 1
5 - 1 6 1 . 0 5
6 - 1 7 7 . 1 6
7 - 1 9 4 . 88
8 - 2 1 4 . 3 7
9 - 2 3 5 . 8 1
1 0 - 2 5 9 . 3 9
Н а ж м и т е < E n t e r > д л я з а в е р ш е н и я п р о г р а м м ы . . .
Итак, взяв длинную, запутанную программу и применив рефакторинг, можно по| чить программу меньшего размера, со сниженным дублированием кода, а главное - бол лее понятную.
Зачем беспокоиться о функциях?
Когда концепция функции появилась в 1950-е годы в Фортране, ее единственной целы! было избежать дублирования кода. Предположим, вы пишете программу, которая доли вычислять и выводить на экран некоторое отношение во многих местах. В этом случае программа может просто вызывать в этих местах функцию D i s p l a y R a t i o ( ) , позво ляющую избежать дублирования кода. Такая экономия может показаться не слишком большой, если функция состоит всего из пары строк, но функции бывают разные; они мо гут быть очень сложными и большими. Кроме того, распространенные функции, наподо бие W r i t e L i n e ( ) , MOiyr использоваться в сотнях различных мест.
Второе преимущество применения функций также очевидно: проще корректно напи сать и отладить одну функцию, чем десяток фрагментов кода, и вдвойне проще еле лать это, если функция невелика. Функция D i s p l a y R a t i o () включает проверку то-
148 |
Часть III. Объектно-основанное программирова |