Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Т Е Х Н О Л О Г І Ї 5 страница




Рис. 24.5. Діаграма дій UML

Діаграми дій можуть також використовуватися для представлення складних алгоритмів, що трапляються в коді програми. В цьому випадку вони практично ідентичні блок-схемам. Вони мають певні додаткові можливості, які ми тут не розглядаємо. Серед них, наприклад, представлення декількох конкуруючих дій.

24.5. Перехід від варіантів використання до класів

Етап побудови програмного забезпечення починається тоді, коли ми переходимо до планування структури програми. Насамперед спробуємо передбачити класи, з яких буде складатися наша програма. Для цього спочатку проаналізуємо перелік іменників з опису варіантів використання, потім внесемо деякі їх уточнення, визначимо їх атрибути, перейдемо від дієслів до повідомлень, і, на завершення, розробимо діаграми класів і послідовностей

24.5.1. Аналіз переліку іменників з опису варіантів використання

Розглянемо перелік усіх іменників, які візьмемо з опису варіантів використання:

1. Вікно інтерфейсу користувача. 2. Мешканець. 3. Вікно введення мешканців. 4. Ім'я мешканця. 5. Номер кімнати. 6. Рядок мешканця. 7. Перелік мешканців. 8. Орендна плата. 9. Вікно введення орендної плати. 10. Місяць. 11. Сума орендної плати. 12. Таблиця доходів від оренди. 13. Рядок орендної плати. 14. Витрата. 15. Вікно введення витрат. 16. Отримувач. 17. Розмір платежу. 18. День. 19. Бюджетна категорія. 20. Рядок у таблиці витрат. 21. Таблиця витрат. 22. Річний звіт. 23. Загальна орендна плата. 24. Загальні витрати за категоріями. 25. Баланс.

24.5.2. Уточнення переліку іменників

З різних причин багато іменників не зможуть стати класами. Давайте проведемо відбір тільки тих іменників, які можуть претендувати на високе звання класів.

Ми виписали назви рядків різних таблиць: рядок мешканців, рядок орендної плати, рядок витрат. Іноді з рядків можуть виходити чудові класи, якщо вони складені або містять складні дані. Але кожен рядок таблиці мешканців містить дані тільки про одного мешканця, кожен рядок у таблиці витрат – тільки про один платіж. Класи мешканців і витрат вже існують, тому ми наважимося припустити, що нам не потрібні два класи з однаковими даними, тобто ми не розглядатимемо рядки мешканців і витрат як претенденти на класи. Рядок орендної плати, з іншого боку, містить відомості про номер кімнати і масив з 12 платежів за оренду по місяцях. Вона відсутня в таблиці до тих пір, поки не буде зроблений перший внесок у поточному році. Подальші платежі вносяться у вже наявні рядки. Це ситуація складніша, ніж з мешканцями і витратами, тому, так і бути, зробимо рядок орендної плати класом. Тоді клас орендної плати як такий не міститиме нічого, окрім суми платежу, тому цей іменник перетворювати на клас ми не станемо.

Програма може породжувати значення в річному звіті з таблиці орендної плати і таблиці витрат, тому, напевно, не варто суму орендних платежів, а також загальні витрати за категоріями і баланс робити окремими класами. Вони є просто результатами обчислень.

Отже, складемо перелік класів, які було тільки що уточнено:

1. Вікно інтерфейсу користувача. 2. Мешканець. 3. Вікно введення мешканців. 4. Перелік мешканців. 5. Вікно введення орендної плати. 6. Таблиця доходів від оренди. 7. Рядок таблиці доходів від оренди. 8. Витрата. 9. Вікно введення витрат. 10. Таблиця витрат. 11. Річний звіт.

24.5.3. Визначення атрибутів

Багато іменників, яким відмовлено в реєстрації як кандидати в класи, будуть потенційними кандидатами в атрибути (компонентні дані) класів. Наприклад, у класу "Мешканці" будуть такі атрибути: ім'я мешканця, номер кімнати. У класу "Витрати": отримувач, місяць, день, сума, бюджетна категорія. Більшість атрибутів можуть бути визначені таким шляхом.

24.5.4. Перехід від дієслів до повідомлень

Тепер подивимося, що нам дають варіанти використання для з'ясування того, якими повідомленнями обмінюватимуться класи. Оскільки повідомлення – це, по суті справи, є викликом методу в об'єкті, то визначення повідомлень зводиться до визначення методів класу, що приймає те або інше повідомлення. Як і у випадку з іменниками, далеко не кожне дієслово стає кандидатом у повідомлення. Деякі з них, замість прийому даних від користувачів, зв'язуються з такими операціями, як виведення інформації на екран, або з якими-небудь ще діями.

Як приклад розглянемо опис варіанту використання функції "Вивести перелік мешканців". Курсивом виділені дієслова:

Програма виводить на екран перелік мешканців, кожен рядок переліку складається з двох полів: номер кімнати і ім'я мешканця.

Під словом "програма" ми насправді маємо на увазі вікно інтерфейсу користувача, отже, слово "виводить" означає, що об'єкт "Вікно інтерфейсу користувача" посилає повідомлення об'єкту "Перелік мешканців" (тобто викликає його метод). У повідомленні має міститься вказівка вивести самого себе на екран. Нескладно здогадатися, що метод може називатися, наприклад, display().

Дієслово "складається" не відноситься ні до якого повідомлення. Він просто приблизно визначає склад рядка об'єкта "Перелік мешканців".

Розглянемо складніший приклад: варіант використання "Додати нового мешканця":

У вікні має відобразитися повідомлення, у якому програма просить користувача ввести ім'я мешканця і номер кімнати. Ця інформація повинна заноситися в таблицю. Перелік автоматично сортується за номерами кімнат.

Дієслово "складається" в даному випадку означатиме наступне. Екран інтерфейсу користувача повинен послати повідомлення класу "Екран введення мешканців", наказуючи йому вивести себе і отримати дані від користувача. Це повідомлення може бути викликом методу класу з іменем, наприклад getTenant().

Дієслова "просить" і "ввести" відносяться до взаємодії класу "Екран введення мешканців" з користувачем. Вони не стають повідомленнями в об'єктному сенсі. Попросту getTenant() виводить запрошення і записує відповіді користувача (ім'я мешканця і номер кімнати).

Дієслово "заноситися" означає, що об'єкт класу "Екран введення мешканців" посилає повідомлення об'єкту класу "Перелік мешканців". Можливо, як аргумент використовується новий об'єкт класу "Мешканці". Об'єкт "Перелік мешканців" може потім вставити цей новий об'єкт у свій перелік. Ця функція може мати ім'я типу insert Tenant().

Дієслово "сортується" – це не ніяке повідомлення і взагалі не вид взаємодії об'єктів. Це просто опис переліку мешканців.

На рис. 24.6 показано варіант використання "Додати нового мешканця" і його зв'язку з описаними вище повідомленнями.

Коли ми почнемо писати код програми, то виявимо, що деякі дії залишилися поза нашим розглядом у цьому варіанті використання, але потрібні програмі. Наприклад, ніде не йдеться про створення об'єкта "Мешканець". Проте, напевно, зрозуміло, що "Перелік мешканців" містить об'єкти типу "Мешканець", а останні повинні бути створені до їх внесення в перелік. Отже, системний інженер вирішує, що метод getTenant() класу "Екран введення мешканців" – це відповідне місце для створення об'єкта "Мешканець", що вставляється в перелік мешканців.

Всі інші варіанти використання повинні бути проаналізовані аналогічним чином, щоб можна було створити основу для зв'язування класів. Зверніть увагу, що ми все ще використовуємо імена класів, що збігаються із словами або словосполученнями варіантів використання. Коли ми почнемо писати код програми, нам, зазвичай, доведеться перейменувати їх у що-небудь прийнятніше (імена повинні складатися з одного слова).

Рис. 24.6. Дієслова варіанту використання "Додати нового мешканця"

24.5.5. Побудова діаграм класів

Знаючи, які класи будуть включені в розроблювану програму і як вони пов'язані між собою, ми зможемо побудувати діаграми класів. У попередніх розділах ми вже бачили приклади таких діаграм. На рис. 24.7 показана діаграма класів програми landlord.

Рис. 24.7. Діаграма класів для програми landlord

24.5.6. Побудова діаграм послідовностей

Перш ніж почати писати код програми, було б логічно з'ясувати детальніше, як виконується кожен крок кожного варіанту використання. Для цього можна побудувати діаграми послідовностей UML. Це один з двох типів діаграм взаємодії UML (другий тип – сумісна діаграма). І на тій, і на іншій відображається, як події розгортаються в часі. Просто діаграма послідовностей наочніше зображає процес перебігу часу. На ній вертикальна вісь – це час. Вона "починається" вгорі і тече зверху вниз за діаграмами. Вгорі знаходяться імена об'єктів, які братимуть участь в даному варіанті використання. Дія зазвичай починається з того, що об'єкт, розташований зліва, посилає повідомлення об'єкту, розташованому справа. Зазвичай чим правіше роз­­ташований об'єкт, тим нижче його значущість для програми або більше його залеж­ність від інших.

Зверніть увагу на те, що на діаграмі показано не класи, а об'єкти. Кажучи про послідовності повідомлень, необхідно згадати, що повідомлення пересилаються саме між об'єктами, а не між класами. На діаграмах UML назви об'єктів відрізняються від назв класів наявністю підкреслення.

Лінією життя називається пунктирна лінія, що йде вниз від кожного об'єкта. Вона показує, коли об'єкт починає і закінчує своє існування. У тому місці, де об'єкт видаляється з програми, лінія життя закінчується.

Діаграма послідовностей для варіанту використання "Почати програму"

Звернемо Вашу увагу на деякі з діаграм послідовностей нашої програми. Почнемо з найпростішою з них. На рис. 24.8 показана діаграма для варіанту використання "Почати програму".

Під час запуску програми визначається userInterface – клас підтримки екрану інтерфейсу користувача, який ми так довго обговорювали, кажучи про варіанти використання. Припустимо, програма створює єдиний об'єкт класу під назвою theUserInterface. Саме цей об'єкт породжує всі варіанти використання. Він з'являється зліва на діаграмі послідовностей. Як бачите, ми на цьому етапі вже перейшли до нормальних імен класів, прийнятих у процесі написання коду програми.

Рис. 24.8. Діаграма послідовностей для варіанту використання "Почати програму"

Коли вступає в роботу об'єкт theUserInterface, перше, що він має виконати, то створити три основні структури даних у програмі. Це об'єкти класів tenantList, rentRecord і expenceRecord. Виходить, що вони народжуються безіменними, оскільки для їх створення використовується new. Імена мають тільки покажчики на них. Як же нам їх назвати? На щастя, як ми переконалися на прикладі об'єктних діаграм, UML надає декілька способів іменування об'єктів. Якщо справжнє ім'я невідоме, то можна використовувати замість нього двокрапку з іменем класу (:tenantList). На діаграмі підкреслення імені і двокрапка перед ним нагадує про те, що ми маємо справу з об'єктом, а не з класом.

Вертикальна позиція прямокутника з іменем об'єкта указує на той момент часу, коли об'єкт був розроблений (першим створюється об'єкт класу tenantList). Всі об'єкти, які Ви бачите на діаграмі, продовжують існувати весь час, поки програма знаходиться на виконанні. Шкала часу, строго кажучи, рисується не в масштабі вона призначена тільки для того, щоб показати взаємозв'язок різних подій.

Горизонтальні лінії є повідомленням (тобто виклики методів). Суцільна стрілка свідчить про нормальний синхронний виклик функції, відкрита – про асинхронну подію.

Прямокутник, розташований під theUserInterface, називається блоком активності (або центром керування). Він показує, що розташований над ним об'єкт є активним. У звичайній процедурній програмі, такій, як наша (landlord), "активний" означає, що метод даного об'єкта або виконується сам, або викликав на виконання іншу функцію, яка ще не завершила свою роботу. Три інші об'єкти на цій діаграмі не є активними, тому що theUserInterface ще не послав їм активізаційних повідомлень.

Діаграма послідовностей для варіанту використання "Виведення переліку мешканців"

Ще один приклад діаграми послідовностей представлено на рис. 24.9. На рисунку зображена робота варіанту використання "Виведення переліку мешканців". Повернення значень функціями показано переривистими лініями. Зверніть увагу: об'єкти активні тільки тоді, коли викликано будь-якій їх метод. Зверху над лінією повідомлення може бути вказано ім'я методу, що викликається.

Що ми бачимо? Об'єкт theUserInterface дає завдання об'єкту tenantList вивести себе на екран (викликом його методу display()), а той, своєю чергою, виводить всі об'єкти класу tenant. Зірочка означає, що повідомлення посилатиметься циклічно, а фраза в квадратних дужках [ для усіх об'єктів tenant ] повідомляє умову повторення[89].

Рис. 24.9. Діаграма послідовностей для варіанту використання "Виведення переліку мешканців"

Діаграма послідовностей для варіанту використання "Додати нового мешканця"

Нарешті, останнім прикладом діаграми послідовностей, який ми тут наводимо, є діаграма для варіанту використання "Додати нового мешканця". Вона показана на рис. 24.10. Сюди ми включили самого домовласника у вигляді об'єкта, який визначає різні дії. У нього є свій власний блок активності. За допомогою цього об'єкта можна повністю показати процес взаємодії користувача з програмою.

Рис. 24.10. Діаграма послідовностей для варіанту використання "Додати нового мешканця"

Користувач повідомляє програму про те, що він бажає додати нового мешканця. Об'єкт theUserInterface створює новий об'єкт класу tenantInputScreen. У цьому об'єкті є методи, що дають змогу отримати від користувача дані про мешканця, створити новий об'єкт типу tenant і викликати метод об'єкта класу tenantList для додавання в перелік знов створеного мешканця. Коли все це виконано, об'єкт theUserInterface віддаляється. Велика буква "X" в кінці лінії життя tenantInputScreen свідчить про те, що об'єкт видалений.

Діаграми послідовностей, приклади яких ми тут навели, мають справу тільки з головними сценаріями кожного варіанту використання. Існують, насправді ж, способи показати на діаграмах і декілька сценаріїв, але можна і для кожного сценарію створити свою діаграму.

Відсутність місця в навчальному посібнику не дає змогу нам навести всі приклади діаграм послідовностей, але, здається, і так вже показано достатньо для їх розуміння.

24.6. Кроки написання коду програми

Опанувавши діаграмами варіантів використання, детальними описами варіантів використання, діаграмами класів і послідовностей, а також попередніми планами щодо створення коду програми, можна запустити компілятор і почати писати сам код програми. Це друга частина етапу її побудови, яка складається з декількох кроків: написання заголовного файлу; створення початкових *.срр файлів; введення вимушеного спрощення коду програми; передбачити взаємодію користувача з програмою.

Варіанти використання, визначені на етапі удосконалення, стають ітераціями на новому етапі (див. рис. 24.2). У великому проекті кожна ітерація може проводитися різними групами програмістів. Всі ітерації повинні проектуватися окремо, а їх результати – надаватися замовнику для внесення доповнень і виправлень. У нашій невеликій| програмі, втім, ці зайві складнощі ні до чого.

24.6.1. Написання заголовного файлу

Ура, ми дісталися до написання таких рідних і звичних файлів з кодами програми. Краще за все починати із заголовного (*.h) файлу, у якому необхідно визначити тільки інтерфейсні частини класів, але не подробиці реалізації. Як зазначалося раніше, оголошення в заголовному файлі – це загальнодоступна частина класів. Тіла функцій, що є розташовані в *.срр-файлах, називаються реалізацією і користувачам недоступні.

Написання заголовного файлу – це проміжний крок між етапами плануванням і звичайним кодуванням методів. Розглянемо вміст заголовного файлу landlord.h.

Код програми 24.1. Заголовний файл до програми landlord

// landlord.h

// Заголовний файл landlord.cpp – містить оголошення класів і т.ін.

#pragma warning(disable:4786)//Для множин (тільки компілятори Microsoft)

#include <iostream> // Для потокового введення-виведення

#include <vector> // Для роботи контейнерним класом "Вектор"

#include <set>

#include <string> // Для роботи з рядками

#include <algorithm> // Для sort ()

#include <numeric> // Для accumulate()

using namespace std; // Використання стандартного простору імен

 

/// Глобальні методи ///

void getaLine(string & inStr); // Отримання рядка тексту

char getaChar(); // Отримання символу

 

class tenant { // Мешканці

private:

string name; // Ім'я мешканця

int aptNumber; // Номер кімнати мешканця

// Тут може бути будь-яка інша інформація про мешканця,

// наприклад, номер телефону і т.ін.

public:

tenant(string n, int aNo);

~tenant();

int getAptNumber(); // Потрібно для використання в множині

friend bool operator < (const tenant&, const tenant&);

friend bool operator == (const tenant&, const tenant&);

// Для операцій введення/виведення

friend ostream & operator << (ostream &, const tenant&);

}; // <------> Кінець оголошення класу tenant

 

// Функціональний об'єкт для порівняння імен мешканців

class compareTenants {

public:

bool operator () (tenant*, tenant*) const;

};

 

// >------> Клас tenantList

class tenantList {

private:

// Встановити покажчики на мешканців

set <tenant*, compareTenants> setPtrsTens;

set <tenant*, compareTenants>:: iterator iter;

public:

~tenantList(); // Оголошення деструктора (Видалення мешканців)

void insert Tenant(tenant*); // Внесення мешканця в перелік

int getAptNo(string); // Повертає номер кімнати

void display(); // Виведення переліку мешканців

};

// <------> Кінець оголошення класу tenantList

 

class tenantInputScreen {

private:

tenantList* ptrTenantList;

string tName;

int aptNo;

public:

tenantInputScreen(tenantList* ptrTL): ptrTenantList(ptrTL)

{ /* тут порожньо */ }

void getTenant();

}; // <------> Кінець класу tenantInputScreen

 

// Один рядок таблиці прибутку: адреса і 12 місячних плат

class rentRow {

private:

int aptNo;

float rent[12];

public:

rentRow(int); // Оголошення конструктора з одним параметром

void setRent(int, float); // Запис плати за місяць

float getSumOfRow(); // Сума платежів з одного рядка

// Потрібно для збереження в множині

friend bool operator < (const rentRow&, const rentRow&);

friend bool operator == (const rentRow&, const rentRow&);

// Для виведення

friend ostream & operator << (ostream &, const rentRow&);

}; // <------> Кінець класу rentRow

 

// Функціональний об'єкт порівняння об'єктів rentRows

class compareRows {

public:

bool operator () (rentRow*, rentRow*) const;

};

 

class rentRecord {

private:

// Множину покажчиків на об'єкти rentRow (по одному на мешканця)

set <rentRow*, compareRows> setPtrsRR;

set <rentRow*, compareRows>:: iterator iter;

public:

~rentRecord();

void insert Rent(int, int, float);

void display();

float getSumOfRents(); // Сума усіх платежів

}; // <------> Кінець класу rentRecord

 

class rentInputScreen {

private:

tenantList* ptrTenantList;

rentRecord* ptrRentRecord;

string renterName;

float rentPaid;

int month;

int aptNo;

public:

rentInputScreen(tenantList* ptrTL rentRecord* ptrRR):

ptrTenantList(ptrTL), ptrRentRecord(ptrRR)

{ /*тут пусто*/ }

void getRent(); // Орендна плата одного мешканця за один місяць

}; // <------> Кінець класу rentInputScreen

 

class expense {

public:

int month, day;

string category, payee;

float amount;

expense() { }

expense(int m, int d, string c, string p, float а):

month(m), day(d), category(c), payee(p), amount(a)

{ /* тут порожньо! */ }

// Потрібно для зберігання в множині

friend bool operator < (const expense&, const expense&);

friend bool operator == (const expense&, const expense&);

// Потрібно для виведення

friend ostream & operator << (ostream &, const expense&);

}; // <------> Кінець класу expense

 

// Функціональний об'єкт порівняння витрат

class compareDates {

public:

bool operator () (expense*, expense*) const;

};

 

// Функціональний об'єкт порівняння витрат

class compareCategories {

public:

bool operator () (expense*, expense*) const;

};

 

class expenseRecord {

private:

// Вектор покажчиків на витрати

vector <expense*> vectPtrsExpenses;

vector <expense*>:: iterator iter;

public:

~expenseRecord();

void insert Exp(expense*);

void display();

float displaySummary(); // Потрібно для річного звіту

}; // <------> Кінець класу expenseRecord

 

class expenseInputScreen {

private:

expenseRecord* ptrExpenseRecord;

public:

expenseInputScreen(expenseRecord*);

void getExpense();

}; // <------> Кінець класу expenseInputScreen

 

class annualReport {

private:

rentRecord* ptrRR;

expenseRecord* ptrER;

float expenses, rents;

public:

annualReport(rentRecord*, expenseRecord*);

void display();

}; // <------> Кінець класу annualReport

 

class userInterface {

private:

tenantList* ptrTenantList;

tenantInputScreen* ptrTenantInputScreen;

rentRecord* ptrRentRecord;

rentInputScreen* ptrRentInputScreen;

expenseRecord* ptrExpenseRecord;

expenseInputScreen* ptrExpenseInputScreen;

annualReport* ptrAnnualReport;

char ch;

public:

userInterface();

~userInterface();

void interact();

}; // <------> Кінець класу userInterfac

 

// <------> Кінець файлу landlord.h

Оголошення класів

Оголошувати класи – це просто. Більшість оголошень зростають безпосередньо з класів, створених за допомогою узятих з описів варіантів використання іменників, і відображаються на діаграмі класів. Тільки імена потрібно зробити однослівними з багатослівних. Наприклад, ім'я "Перелік мешканців" (Tenant List) перетворюється в TenantList.

У заголовному файлі було додано ще декілька допоміжних класів. Згодом виявиться, що ми зберігаємо покажчики на об'єкти в різних типах контейнерів STL. Це означає, що ми повинні порівнювати об'єкти цих контейнерів так, як це описано в розд. 21 "Введення в стандартну бібліотеку шаблонів (STL)". Об'єктами порівняння насправді є класи compareTenants, compareRows, compareDates і compareCategories.

Описи атрибутів

Як вже було зазначено вище, багато атрибутів (методи) для кожного з класів є похідними з тих іменників, які самі не стали класами. Наприклад, name і aptNumber стали атрибутами класу tenant.

Інші атрибути можуть бути виведені з асоціацій в діаграмі класів. Асоціації можуть визначати ті атрибути, які є покажчиками або посиланнями на інші класи. Це пояснюється неможливістю асоціювати щось з чимось, що знаходиться невідомо де. Таким чином, у класі rentInputScreen з'являються атрибути ptrTenantList і ptrRentRecord.

Складені значення (агрегати)

Агрегатні зв'язки показані в трьох місцях на діаграмі класів. Зазвичай агрегати виявляють ті контейнери, які є атрибутами агрегатного класу (тобто "цілого" класу, що містить "частини").

Ні за описами варіантів використання, ні за діаграмами класів неможливо вгадати, якого роду контейнери повинні використовуватися для цих агрегатів. Вам як програмістам доведеться самим щоразу вибирати відповідний контейнер для кожного складеного значення – будь-то простий масив, контейнер STL або що-небудь ще. У програмі landlord ми зробили такий вибір:

● клас tenantList містить STL-множину покажчиків на об'єкти класу tenant;

● клас rentRecord містить множину покажчиків на об'єкти класу rentRow;

● клас expenseRecord містить вектор покажчиків на об'єкти класу expense.

Для tenantList і rentRecord ми вибрали множини, оскільки основним параметром є швидкий доступ до даних. Для expenseRecord вибрані вектор, тому що нам важливо здійснювати швидке сортування і за датою, і за категоріями, а вектори дають змогу сортувати дані найефективніше.

У всіх агрегатах ми вважали за краще зберігати покажчики замість самих об'єктів, щоб уникнути зайвого копіювання даних у пам'яті. Зберігання самих об'єктів необхідно застосовувати в тих випадках, коли об'єктів мало і вони невеликі. Зазвичай, великої різниці в швидкості на прикладі якихось 12 екземплярів об'єкта ми не побачимо, але у принципі про ефективність методу зберігання даних необхідно замислюватися завжди.

24.6.2. Створення початкових *.срр файлів

У початкових файлах містяться тіла методів, які були оголошені в заголовному файлі. Написання коду програми цих методів має починатися тільки на цьому етапі розроблення ПЗ і ні кроком раніше, тому що тільки зараз ми знаємо ім'я кожної функції, її призначення і навіть, можливо, можемо передбачити аргументи, що передаються їй.

Ми відокремили зерна від полови: main () зберігаємо в одному коротенькому файлі lordApp.cpp, а визначення функцій, оголошених у заголовному файлі, – в іншому. У секції main () створюється об'єкт userInterface і викликається метод interact(). Наведемо файл, у якому зберігається main ().




Поделиться с друзьями:


Дата добавления: 2014-11-29; Просмотров: 491; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.