ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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. Объектно-основанное программирова