LINUX.ORG.RU

[C++],[быдлокод] Помаленьку учу плюсы (часть 2 из много)

 ,


0

1

Я периодически буду тут на форуме задавать вопросы или обращаться с просьбой к уважаемому комьюнити.
Собственно, в очередной раз обращаюсь с просьбой:
Раскритиковать, сказать в чём улучшить, что не следует делать и что следует делать.
Постарался разобраться с классами, хотя многое пока всё равно не до конца понятно. Если есть улучшения по сравнению с предыдущим топиком - скажите, буду рад это слышать.

main.cpp
basic_invest.h

Сразу вопрос, который и так возник: стоит ли разные классы выделять в разные заголовочные файлы, естественно в случае более крупного проекта. Правильно понимаю, что их стоит разбивать про принципу функционала и того, в каких .cpp файлах они используются/не используются?

В общем - ругайте. Это полезно)

Ответ на: комментарий от CyberTribe

Ты невнимательно смотрел. Смотри внимательно ещё раз - всё там элементарно получается

Led ★★★☆☆
()
Ответ на: комментарий от CyberTribe

>Вот последний вариант мне нравится.

Как это может нравиться? Зачем ДВАЖДЫ проверять одно и то же условие? Зачем в цикл пихать действия, которые выполняются ОДИН раз - уже, по-факту, вне цикла?

Led ★★★☆☆
()
Ответ на: комментарий от Led

Какое действие выполняется по факту один раз вне цикла?
Добавил комментарии - где я не прав?

  do //пока значение переменной length <= 0 выполняется цикл
  { 
   cout << "Input the length of project" << endl; 
   cin >> length; // считываем значение переменной length
   if ( length <= 0 ) {  // если length <= 0 то говорим об ошибке и выполняем цикл снова - снова считываем значение
     cerr << "Wrong length of project" << endl;  
     cerr << "The length of project must be greater then 0" << endl;  
   }  
  } 
  while (length <= 0); 

CyberTribe ★★
() автор топика
Ответ на: комментарий от CyberTribe

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


Виноват, «проморгал»:)

Тогда так:

for (;;) {
cout << «Input the length of project» << endl;
cin >> length;
if ( length <= 0 ) {
cerr << «Wrong length of project» << endl;
cerr << «The length of project must be greater then 0»<<endl;
continue;
}
}

Led ★★★☆☆
()
Ответ на: комментарий от CyberTribe

>Какое действие выполняется по факту один раз вне цикла?

Написал уже выше: я ошибся, «проморгав», что условие выхода по «не-ошибка», а не по «ошибка»

Led ★★★☆☆
()
Ответ на: комментарий от Led

Да я понял. я вопрос свой раньше написал чем вы ответили)

CyberTribe ★★
() автор топика
Ответ на: комментарий от Led

Вот исправленный код (таки заставили меня асилить LORCODE:)

for (;;) {
    cout << "Input the length of project" << endl; 
    cin >> length;
    if ( length > 0 )
        break;
    cerr << "Wrong length of project" << endl;
    cerr << "The length of project must be greater then 0" << endl;
}
Led ★★★☆☆
()
Ответ на: комментарий от CyberTribe

>хотя уж до этого я и сам догадался

Это радует.

Led ★★★☆☆
()

Вот мои пожелания:

1. В *.h файлах следует оставлять _только_ определения класса. Всю реализацию необходимо выносить в *.cpp файлы.

2. Если уж ты взялся писать на английском, то тогда coefficients или factors, но не koefficients.

3. Пожелание освоить argc и argv. Ну или *.data файл, через который скармливать весь набор параметров. Сейчас интерактивные приложения для shell никому не интересны.

4. Я бы еще весь код, который делает реальную работу из main вынес в отдельную функцию.

trex6 ★★★★★
()
Ответ на: комментарий от CyberTribe

По main.cpp:

1. Функцию data_input следует заменить на две функции чтения. Модифицировать переданные в функцию переменные - это плохая привычка. Лучше ничего не передавать в функцию, а просто возвращать прочитанное значение. Как-то так:

int read_length () {
    int length;
    while (true) {
        std::cout << "Input the length of the project" << std::endl;
        // TODO А по-хорошему, надо считывать строку, а потом проверять, что в этой строке число.
        // В текущей реализации будет наблюдаться очень весёлый эффект, если вместо числа ввести буковки ;)
        std::cin >> length;
        if (length > 0)
            break;
        std::cerr << "bla-bla" << std::endl;
    }
    return length;
}

long double read_discount () {
    // Полностью аналогично. Кстати, что такое discont? Я не знаю такого слова :)
    return discount;
}
Соответственно, в main() будет достаточно написать:
int length = read_length ();              // бывший period
long double discount = read_discount ();  // бывший percent
Если захочешь поместить этот код в класс, суть не изменится: модификация аргумента, переданного по ссылке - это Зло, от которого следует избавляться.

2. Класс results прямо так и просит, чтобы ему передавали параметры не в каждый метод по отдельности, а сразу в конструктор. И оператор << ему тоже не помешает. Это типичный образец паттерна рефакторинга функциональная зависимость (feature envy).

Изменения:

#include <ostream>
class results {
public:
    results (int length, long double discount, cach_flow const& inv, cach_flow const& rev, cf_calc const& flows, koefficients const& disc, koefficients const& infl);

    long double profit_index ();
    long double npv ();
    float profit_period ();
    // and so on...
    friend std::ostream& operator<< (std::ostream& stream, results& res);

private:
    int _length;
    long double _discount;
    // and so on...
};
В новой версии методы класса обращаются к собственным атрибутам экземпляра класса results. Например:
long double results::npv () {
    return _flows .accum_output (_length);
}
Оператор вывода будет выглядеть следующим образом:
std::ostream& operator<< (std::ostream& stream, results& res) {
    stream << "NPV of this project = " << res.npv () << std::endl
           << "Index of profit     = " << res.profit_index () << std::endl
           ...
           << "IRR                 = " << res.irr_calc () << std::endl;

    return stream;
}
А код в main сократится до следующего:
results calculations (length, discount, invest, revenue, other_flows, k_disc, k_infl);
std::cout << calculations;
Конечно, в конструктор передаётся до хрена параметров, что не является признаком хорошего кода, но это можно решить дальнейшим рефакторингом используемых в results классов (который я здесь уже не буду рассматривать, это проделывается аналогично написанному выше).

3. Общие замечания.

3.1. Использовать правильное написание терминов. Мой основной язык - русский, но всё равно слова типа discont или cash режут глаз, и на их понимание требуется лишнее время.

3.2. Не использовать разные термины для одного и того же понятия. А то в одном месте length, а в другом period, в одном discont, а в другом percent. Надо определиться и использовать один и тот же термин.

3.3. Крайне желательно помечать все методы, которые не меняют содержимого класса, как const:

long double koefficients::output (int step) const {
    return priv_disc [step];
}
Это очень полезная привычка при работе с С++. В данном примере она позволит лучше отделить инициализацию данных от использования. А по жизни она помогает писать более надёжный и безопасный код.

Zloddey
()

Убери using из .h'ника и замени long double на double.

Reset ★★★★★
()

еще у тебя в h'нике куча отдельно стоящих функций без inline, либо внеси их прям внутрь классов либо поставь inline иначе с линковкой у тебя проблемы возникнут

Reset ★★★★★
()
Ответ на: комментарий от Led

проллетариату стОит

А ты, я смотрю, C++ раньше русского языка выучил?
Может, ну их, эти форумы? Уткнись в IDE и пиши красивый код на плюсах %)

чисткой сортиров

Е*аный стыд. Чисткой сараев.

power
()
Ответ на: комментарий от Nakgidveef

std::cout << «Hello, World» << std::endl;

Это слишком загромождает код. std еще ладно, но например для бустовых библиотек префиксы получаются длинноваты.

use typedef, Luke :)

shty ★★★★★
()
Ответ на: комментарий от power

>Е*аный стыд. Чисткой сараев.

Да, стыдно. По этой ошибке я себе слив засчитал:)

Led ★★★☆☆
()

koefficients k_disc(period); k_disc.discont(percent);// creating koefficients of discount

Ужасно. Пиши по одной инструкции на строку, и почитай про стили комментариев. Всех серунов не слушай, со временем всё получится, если есть желание.

ShTH
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.