Войти

Показать полную графическую версию : правильность написания кода


Страниц : [1] 2 3

nomad____1
24-04-2015, 11:28
Здравствуйте. Интересует правильно ли я пишу код. Выучил ООП и сейчас перехожу к изучению awt, swing и javaFX. Быстро накидал простенькую прожку. :drug: Хотелось знать мнение по поводу составления кода :read: .



package square;

import square.Triangle;

public class Square {

public static void main(String[] args) {
Triangle triangle = new Triangle(3, 4, 5);
triangle.squareOut();
}
}




package square;

public class Triangle {

private int aSide;
private int bSide;
private int cSide;
private double square;
private double perimeter;

public Triangle(int aSide, int bSide, int cSide) {
this.aSide = aSide;
this.bSide = bSide;
this.cSide = cSide;
}

private void print(String str) {
System.out.println(str);
}

public void square() {
perimeter = (aSide + bSide + cSide) / 2;
square = Math.sqrt(perimeter * (perimeter - aSide) * (perimeter - bSide) * (perimeter - cSide));
}

public void squareOut() {
this.square();
print("Площадь треугольника равна " + square);
}
}

lxa85
24-04-2015, 13:21
Код как код. Не обременен комментариями, не выполняет каких-либо сверх задач, содержит ошибку вычисления при реализации прямоугольного треугольника.
На мой взгляд процедура public void squareOut() { ... } лишняя.
Я не люблю, когда за меня думает процедура. Т.е. я сам решу, какой текст следует писать, и нужен ли он мне вообще.
Из более грубых ошибок - отсутствие проверки треугольника. Т.е. нельзя в планиметрии получить треугольник со сторонами 1, 1, 6.
А в этой программе можно. Тоже касается и отрицательных величин.

Iska
24-04-2015, 13:32
Т.е. нельзя в планиметрии получить треугольник со сторонами 1, 1, 6.
А в этой программе можно. Тоже касается и отрицательных величин. »
Неевклидовость. Антивселенная. ;).

nomad____1
24-04-2015, 14:04
Код как код. Не обременен комментариями, не выполняет каких-либо сверх задач, содержит ошибку вычисления при реализации прямоугольного треугольника.
На мой взгляд процедура public void squareOut() { ... } лишняя.
Я не люблю, когда за меня думает процедура. Т.е. я сам решу, какой текст следует писать, и нужен ли он мне вообще.
Из более грубых ошибок - отсутствие проверки треугольника. Т.е. нельзя в планиметрии получить треугольник со сторонами 1, 1, 6.
А в этой программе можно. Тоже касается и отрицательных величин. »
Благодарю за ответ. Комментарии писать буду, а то я забываю что кроме меня еще кто то будет его читать. Насчет правил планиметрии так сказать "проверку на дурака" я не писал... просто хотел по быстрому накидать прожку. Сегодня допишу с учетом всех ошибок и скину сюда. Интересовало мнение насчет построения класса, методов, конструктора. Благодарю за критику. Если вы не против то по мере изучения я буду сливать сюда коды. Хотелось бы видеть от вас критику по их поводу. Мне кажется просто что так я научусь писать более менее нормальный код.

nomad____1
24-04-2015, 16:40
Еще можно ли использовать геттеры и сеттеры? А то много негативного о них в интернете написано... Или их использование будет дурным тоном?

lxa85
24-04-2015, 22:00
В "интернетах" много что пишут. Если специфика работы объекта подсказывает использования сеттера или геттера - то вполне.
Если сеттер и геттер "поганит" данные и вызывает неявное/непредсказуемое действие - тогда это проблема.
nomad____1, setter и getter - это инструмент. Пользоваться им или нет - решать не мне.
В данном случае в процедуру установки параметров можно прописать процедуру установки флага "валидности" треугольника.
Тогда в процедуре вычисления площади будет проверяться условие планарности треугольника по флагу.
Моветон?
----
nomad____1, как вам сказать. Точность - вежливость королей. По таким мелочам судят о специалисте.
На счет построения конструктора класса и методов - сказать сложно. Ваш пример с одной стороны достаточно каноничен и в нем нет сложности, с другой оторван от реальности и практики.
Те же прямоугольные треугольники здесь не учитываются. Ответ будет дан с определенной погрешностью (кстати вопрос "на засыпку" как специалисту: какая погрешность метода при вычислении площади прямоугольного треугольника?).
Отсутствие условий планиметрии приведет к ошибке - вычислению корня из отрицательного числа (NaN).
----
Iska, а вот интересно. Допустим у нас некая выпуклая фигура, на плоскости которой я могу нарисовать треугольник со сторонами 1:1:6. И ... наверно собственно все. По данным сторонам я не смогу сказать какая это фигура? Допустим шар, сфера.
Наверно нет.
Получится у меня должны (пусть катеты) две стороны лежать на прямых плоскостях, а гипотенуза в 6 ед. должна быть свернута в гармошку.
Так что ли?
----
P.S. Не стоит без особой надобности выделять текст жирным шрифтом.

nomad____1
26-04-2015, 15:48
]В данном случае в процедуру установки параметров можно прописать процедуру установки флага "валидности" треугольника.
Тогда в процедуре вычисления площади будет проверяться условие планарности треугольника по флагу.[/I] »
Сделал. Не знаю так ли как Вы написали.
// Проверка планарности треугольника
if ((aSide + bSide) > cSide && (aSide + cSide) > bSide && (bSide + cSide) > aSide) {
// Вычисление площади
Точность - вежливость королей. По таким мелочам судят о специалисте. »

Программу буду улучшать по мере изучения :beta:

Ваш пример с одной стороны достаточно каноничен и в нем нет сложности, с другой оторван от реальности и практики. »
Те же прямоугольные треугольники здесь не учитываются. Ответ будет дан с определенной погрешностью (кстати вопрос "на засыпку" как специалисту: какая погрешность метода при вычислении площади прямоугольного треугольника?).
Отсутствие условий планиметрии приведет к ошибке - вычислению корня из отрицательного числа (NaN). »

Вы сами дали ответ на свой вопрос) точность! в прямоугольном треугольнике площадь равна (а*b)/2 ... очень высокая точность!) А вот вычисление квадратного корня с числа например 2 или 3....)

Тут уже вопрос как заставить ее работать... У меня выводит 0. Так как не может вычислить целый квадратный корень.

P.S. Не стоит без особой надобности выделять текст жирным шрифтом. »

Это чисто для себя. Так сказать "вопрос-ответ". Выделение своих сообщений (вопросов). Для более простейшей навигации.

Вот код после доработки:
package square;

public class Square {

public static void main(String[] args) {
Triangle triangle = new Triangle(2, 5, 6);
triangle.squareOut();
}
}

package square;

public class Triangle {

private int aSide;
private int bSide;
private int cSide;
private double square;
private double perimeter;
private int vuvod;

public Triangle(int aSide, int bSide, int cSide) {
this.aSide = aSide;
this.bSide = bSide;
this.cSide = cSide;
}

private void print(String str) {
System.out.println(str);
}

//
// Проверка "на дурака" введенных значение и вычисление площади
//
public void square() {
// Проверка нет ли стороны с отрицательным значением или равным нулю
if (aSide <= 0 || bSide <= 0 || cSide <= 0) {
vuvod = 1;
} else {
// Проверка планарности треугольника
if ((aSide + bSide) > cSide && (aSide + cSide) > bSide && (bSide + cSide) > aSide) {
// Вычисление площади
perimeter = (aSide + bSide + cSide) / 2;
square = Math.sqrt(perimeter * (perimeter - aSide) * (perimeter - bSide) * (perimeter - cSide));
vuvod = 2;
} else {
// Когда данные числа не могут соответствовать длине сторон треугольника
vuvod = 3;
}
}
if (square == 0) {
vuvod = 0;
}
}

//
// Вывод значения на экран
//
public void squareOut() {
this.square();
switch (vuvod) {
case 1:
print("Длинна не может быть отрицательным числом");
break;
case 2:
print("Площадь треугольника равна " + square);
break;
case 3:
print("У треугольника не может быть сторон с такими значениями");
break;
default:
print("\tхм... что то не так с программой... Советую заглянуть в метод square... \n\t Скорее всего программа не может добыть квадратный корень. ");
}
}
}


P.S.
Сегодня ночью думаю скину код где будет проверка треугольника на прямоугольность и вычисление площади по отдельной формуле. Думаю использовать сравнение трех сторон. Две самые "мелкие" должны быть катетами. Дальше с помощю теоремы Пифагора проверить будет ли получена гипотенуза равна "нашей" введеной. пока мой извращенный мозг более простого не придумал))) :durak:

P.P.S.
Надеюсь етот смайл пробет стенку головой)

User001
26-04-2015, 16:56
Допустим у нас некая выпуклая фигура, на плоскости которой я могу нарисовать треугольник со сторонами 1:1:6. И ... наверно собственно все. По данным сторонам я не смогу сказать какая это фигура? Допустим шар, сфера. Наверно нет. »Жуть.
А по теме мои 5 копеек:
private int vuvod; »Поменяйте название переменной.
case 1: »
case 2: »Если так и пойдет дело, потом тяжело будет угадывать что это за магические константы.
public void square() { »
public void squareOut() »Лучше это переделать. Как вариант, square возвращает площадь или что-то в этом роде. В вашем случае непонятно зачем square() public.
vuvod = 0; »Его в switch нет.
Длинна не может быть отрицательным числом»Бросается в глаза.

nomad____1
26-04-2015, 17:32
vuvod = 0; »
Его в switch нет.
Цитата nomad____1:
Длинна не может быть отрицательным числом» »

если я правильно понял то 0 это дефолтное значение.

Цитата nomad____1:
case 1: »
Цитата nomad____1:
case 2: »
Если так и пойдет дело, потом тяжело будет угадывать что это за магические константы. »

Это да косяк. Забываю. С СИ начинал учить программирование.

Насчет неправильного вывода то разобрался что нужно поменять типы данных переменных в которые записываются длинны сторон на флоаты или даблы.

lxa85
26-04-2015, 19:20
nomad____1, касательно public'ов, static'ов и пр. я не скажу. Но переменная vuvod у меня вызывает подозрения.
Почему используется конструкция public void SquareOut.
Почему не int или не double ?
Я от программы хочу получить ответ. Желательно наиболее простой и пригодный для "дальнейшей эксплуатации".
Мне совершенно не хочется заниматься парсингом строки (притом не возвращаемой в силу void).
Чтобы сигнализировать об ошибке следует возвращать отрицательные значения. -1, -2 и т.д.
Поведение разумеется должно быть описано в сопровождающей документации и в комментариях к процедуре.
----
Сделал. Не знаю так ли как Вы написали. »
Нет. Я сказал написать проверку в процедуре установки параметров, а не в процедуре вычисления площади.
Напомню, речь шла про сеттеры, гетторы и ввод "флага валидности" треугольника.
----
Две самые "мелкие" должны быть катетами »
А вдруг нет? Вдруг "мелкие" не катят?!! :o

nomad____1
26-04-2015, 20:16
А вдруг нет? Вдруг "мелкие" не катят?!! »

Если треугольник прямоугольный, то самой длинной стороной будет гипотенуза. Значит две остальные - катеты. То есть хочу сделать проверку и найти самую длинную сторону. Что бы разделить на "воображаемые" катеты и гипотенузу. А дальше по теореме Пифагора. Квадрат гипотенузы равняется суме квадратов катетов. И это только для ПРЯМОУГОЛЬНОГО треугольника! Поднести в квадрат нашу самую большую сторону и получить суму квадратов двух других. И сравнить их. Если совпадут то прямоугольный, а если нет то он не прямоугольный. Такой способ проверки я выбрал потому что на даном этапе моя программа использует теорему Герона (площадь вычисляется по длине сторон). А если треугольник прямоугольный то площадь будет равна половине их произведения (опять же надо две самые короткие стороны потому что между ними прямой угол).
---
Нет. Я сказал написать проверку в процедуре установки параметров, а не в процедуре вычисления площади.
Напомню, речь шла про сеттеры, гетторы и ввод "флага валидности" треугольника. »

Я понял) Простите просто "процедура" это как я понял "Метод". То есть в конструкторе (метод) через который устанавливаются значения, прописать проверку на принадлежность фигуры к треугольникам с точки зрения классической планиметрии. Но это неправильно так как "засорять" особо конструкторы не следует. Или создать отдельный метод с типом boolean, который возвращал значение лож и правда.

P.S.
ПРОГРАММУ ПЕРЕПИШУ И СЕГОДНЯ БУДЕТ НОВЫЙ КОД

Iska
26-04-2015, 21:08
Iska, а вот интересно. Допустим у нас некая выпуклая фигура, на плоскости которой я могу нарисовать треугольник со сторонами 1:1:6. И ... наверно собственно все. По данным сторонам я не смогу сказать какая это фигура? Допустим шар, сфера.
Наверно нет.
Получится у меня должны (пусть катеты) две стороны лежать на прямых плоскостях, а гипотенуза в 6 ед. должна быть свернута в гармошку.
Так что ли? »
В свёрнутом в очень широкий и низкий конус пространстве, полагаю: катеты исходят из вершины конуса, а гипотенуза «обёрнута» вокруг основания, не?

lxa85
26-04-2015, 23:54
nomad____1, разница и игра слов процедура/метод от меня ускользают.
Будете приводить код, выделите пожалуйста, чтобы мы говорили об одном и том же.
----
nomad____1, А вдруг нет? Вдруг "мелкие" не катят?! »
Это была шутка :) Игра слова катет и катят.
Iska, вообще подходит. Можно будет взять конус в довольно большом промежутке параметров и рассечь наклонной плоскостью. Это даст эллипс в сечении и останется только достроить треугольник до заданного.

User001
27-04-2015, 07:04
если я правильно понял то 0 это дефолтное значение »Нет (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html).

nomad____1
27-04-2015, 09:21
Цитата nomad____1:
если я правильно понял то 0 это дефолтное значение »
Нет. »
Если ни один параметр не подходит то выбирается дефолтное значение. В даном случае если дорабатывать программу то возможное появление вариантов 4,5.....n , а 0 значение я оставил пустым. То есть 0 не входит в диапазон выбора. Таким способом будет выполнятся дефолт. Потому что в даном случае любое значение переменной больше 3 будет приводить к дефолтному значению. А как по мне это некрасиво. Что где то там есть далеко-далеко дефолт под каким то числом. А при дополнении программы возможно придется число увеличивать. А так под рукою. Нулевое значение = пустое значение = умолчание (дефолт).
P.S.
Благодарю за поправку. Я ничего не доказываю просто объяснил точку зрения "почему я сделать так"... еще вчера после вашего сообщения все операторы выбора были заменены на строковые значения для большей информативности. Параметр "error" не был описан и по нему выполняется дефолтное значение.
P.P.S.
Начал изучать графический интерфейс. Скоро "упакую" эту прожку как конфетку и добавлю немного функционала. А пока надо ее довести до нормального вида.

nomad____1
28-04-2015, 14:45
nomad____1, разница и игра слов процедура/метод от меня ускользают.
Будете приводить код, выделите пожалуйста, чтобы мы говорили об одном и том же. »

И от меня тоже.... :shot:


//
// Проверка "на дурака" введенных значений, проверка планарности треугольника, проверка на прямоугольность
//
private void triangleTest() {
// Проверка нет ли стороны с отрицательным значением или равным нулю
if (aSide <= 0 || bSide <= 0 || cSide <= 0) {
otvet = "minusovoe";
} else {
// Проверка планарности треугольника
if (((aSide + bSide) > cSide && (aSide + cSide) > bSide) && (bSide + cSide) > aSide) {
testTriangl = true;
} else {
// Данные числа не могут соответствовать длине сторон треугольника
otvet = "nesootvetstvie";
testTriangl = false;
}
}
// Проверка на прямоугольность
if (testTriangl == true) {
float masivStoron[] = {aSide, bSide, cSide};
Arrays.sort(masivStoron);
if ((masivStoron[2] * masivStoron[2]) == (masivStoron[0] * masivStoron[0] + masivStoron[1] * masivStoron[1])) {
rightTriangle = true;
}
}
}


Это была шутка Игра слова катет и катят. »
Простите. Я не хотел обидеть. Без злости и задней мысли все пишу. Я просто так раскрываю свою точку зрения. Еще раз прошу прощения если показался дерзким или где то хамил.

А вот и полностью сам код!


package square;

public class Square {

public static void main(String[] args) {
Triangl triangle = new Triangl(3, 4, 5);
triangle.valueOut();
}
}





package square;

import java.util.Arrays;

public class Triangl {

private float aSide;
private float bSide;
private float cSide;
private double square;
private double perimeter;
private String otvet;
private boolean testTriangl;
private boolean rightTriangle;
private float masivStoron[];

public Triangl(int aSide, int bSide, int cSide) {
this.masivStoron = new float[]{aSide, bSide, cSide};
this.aSide = aSide;
this.bSide = bSide;
this.cSide = cSide;
}

//Собственный метод вывода
private void print(String str) {
System.out.println(str);
}

//
// Проверка "на дурака" введенных значений, проверка планарности треугольника, проверка на прямоугольность
//
private void triangleTest() {
// Проверка нет ли стороны с отрицательным значением или равным нулю
if (aSide <= 0 || bSide <= 0 || cSide <= 0) {
otvet = "minusovoe";
} else {
// Проверка планарности треугольника
if (((aSide + bSide) > cSide && (aSide + cSide) > bSide) && (bSide + cSide) > aSide) {
testTriangl = true;
} else {
// Данные числа не могут соответствовать длине сторон треугольника
otvet = "nesootvetstvie";
testTriangl = false;
}
}
// Проверка на прямоугольность
if (testTriangl == true) {
float masivStoron[] = {aSide, bSide, cSide};
Arrays.sort(masivStoron);
if ((masivStoron[2] * masivStoron[2]) == (masivStoron[0] * masivStoron[0] + masivStoron[1] * masivStoron[1])) {
rightTriangle = true;
}
}
}
//
// Вычисление площади
//

private void square() {
if (testTriangl == true) {
if (rightTriangle == true) {
square = masivStoron[0] * masivStoron[1] / 2;
} else {
if (testTriangl == true) {
perimeter = (aSide + bSide + cSide) / 2;
square = Math.sqrt(perimeter * (perimeter - aSide) * (perimeter - bSide) * (perimeter - cSide));
}
}
otvet = "uspeshno";
}
}
//
// Вывод ответа
//

public void valueOut() {
this.triangleTest();
this.square();
switch (otvet) {
case "minusovoe":
print("Длина не может быть отрицательным числом");
break;
case "uspeshno":
print("Треугольник -" + testTriangl + "\nПрямоугольный -" + rightTriangle);
System.out.printf("Площадь треугольника равна %.2f кв.ед\n", square);
break;
case "nesootvetstvie":
print("У треугольника не может быть сторон с такими значениями");
break;
default:
print("\tхм... что то не так с программой... ");
}
}
}

lxa85
28-04-2015, 18:25
Простите. Я не хотел обидеть. »
а я и не обижался :)

private void square() {
if (testTriangl == true) {
if (rightTriangle == true) {
square = masivStoron[0] * masivStoron[1] / 2;
} else {
if (testTriangl == true) {
perimeter = (aSide + bSide + cSide) / 2;
square = Math.sqrt(perimeter * (perimeter - aSide) * (perimeter - bSide) * (perimeter - cSide));
}
}
otvet = "uspeshno";
}
}
Двойная проверка условия testTriangle.


public void valueOut() {
this.triangleTest();
this.square();
switch (otvet) {
case "minusovoe":
print("Длина не может быть отрицательным числом");
break;
case "uspeshno":
print("Треугольник -" + testTriangl + "\nПрямоугольный -" + rightTriangle);
System.out.printf("Площадь треугольника равна %.2f кв.ед\n", square);
break;
case "nesootvetstvie":
print("У треугольника не может быть сторон с такими значениями");
break;
default:
print("\tхм... что то не так с программой... ");
}
}
Забудьте вы про то, что класс должен что то писать в консоль! Не его это задача. Соотв. что за глупая переменная otvet ? У нее от силы 4 значения, а ей аж строковая переменная отдана.
Класс как результат вычисления square должен отдавать либо результат вычисления площади, либо отрицательное число с ошибкой.
Анализ ошибки на стороне "пользователя" класса.
Если уж хотите что-нибудь писать, пишите в стандартный поток ошибок. А заодно узнайте, что это за звери - стандартный поток ввода, стандартный поток вывода, стандартный поток ошибок. Заодно прочитайте про волшебную вещь перенаправления потоков.

Анализ планарности треугольника происходит каждый раз при вычислении площади. Что ИМХО не есть правильно.
Выставление флагов планарности и прямоугольности ИМХО должно выставляться в процессе задания параметров треугольника. (Сеттеры и геттеры)

nomad____1
28-04-2015, 19:18
Забудьте вы про то, что класс должен что то писать в консоль! Не его это задача. Соотв. что за глупая переменная otvet ? У нее от силы 4 значения, а ей аж строковая переменная отдана.
Класс как результат вычисления square должен отдавать либо результат вычисления площади, либо отрицательное число с ошибкой.
Анализ ошибки на стороне "пользователя" класса.
Если уж хотите что-нибудь писать, пишите в стандартный поток ошибок. А заодно узнайте, что это за звери - стандартный поток ввода, стандартный поток вывода, стандартный поток ошибок. Заодно прочитайте про волшебную вещь перенаправления потоков.
Анализ планарности треугольника происходит каждый раз при вычислении площади. Что ИМХО не есть правильно.
Выставление флагов планарности и прямоугольности ИМХО должно выставляться в процессе задания параметров треугольника. (Сеттеры и геттеры) »
Благодарю. Понял. Перепишу. Почему именно в консоль? Да потому что я только выучил в яве основы ООП. А точнее я учил ее три дня по пол часа когда выложил первый код. Я только еще на старте. До многопоточности еще далеко. С типом метода int, float, boolean и т.д. у меня немножко проблемы. До конца не могу понять. Так что когда разберусь перепишу и выложу. А тем временем поучу свинги что бы не в консольку вводить и выводить) У меня просто сумасшедший план. За месяц выучить ООП (уже почти полностью прошел и более менее разобрался), основы свингов, авт и ява FX, основы баз данных. Очень хочу чем поскорее устроится на стажировку (желательно оплачиваемую). Анриал? Я думаю ДА))))

Анализ планарности треугольника происходит каждый раз при вычислении площади. Что ИМХО не есть правильно.
Выставление флагов планарности и прямоугольности ИМХО должно выставляться в процессе задания параметров треугольника. (Сеттеры и геттеры) »
Просто я использовал Конструктов вместо сеттеров и геттеров для установки параметров.

Двойная проверка условия testTriangle. »

Что то недоглядел

Если уж хотите что-нибудь писать, пишите в стандартный поток ошибок. А заодно узнайте, что это за звери - стандартный поток ввода, стандартный поток вывода, стандартный поток ошибок. Заодно прочитайте про волшебную вещь перенаправления потоков. »
За это огромнейшее спасибо!!!. Обязательно прочту.

lxa85
28-04-2015, 21:04
nomad____1, Конструктор - он конструирует. Он выполняется один раз при создании объекта. Объект создали, далее конструктор мы не дергаем.
А вот установку параметров (св-тв) объекта - это другая, более интересная и захватывающая история.
Св-ва (поля) планарности и "прямоугольности" объекта Triangle надо сделать закрытыми (private), чтобы я не мог влиять на них извне.

Ситуация.
Я ввожу треугольник (1, 1, 6). Процедура установки параметров отрабатывает ситуацию и сбрасывает флаг планарности.
Процедура вычисления площади, написанная как
if planarity {square = ...} else {...};
отдаст ошибку. При этом я пологая, что для вычисления площади я не буду каждый раз "рассчитывать" условия планарности.
Тогда я принудительно говорю объекту, что он планарен (triangle.planarity = true) и все, здравствуй не верная площадь.
Поэтому признаки должны быть скрытыми (private)
Модификация признаков - в процессе установки сторон треугольника. (Setter (https://ru.wikipedia.org/wiki/Setter)

User001
30-04-2015, 10:20
До многопоточности еще далеко. »lxa85 имел ввиду потоки ввода / вывода.
Triangl»Букву жалко?
case "minusovoe": »
case "uspeshno": »
Использовать строки весьма расточительно. Смотрите в сторону enum (http://stackoverflow.com/questions/8108980/java-using-enum-with-switch-statement).
Соотв. что за глупая переменная otvet ? »Дополню. Вот тут (https://learn.javascript.ru/variable-names) про JS, но суть одинаковая. Обратите внимание на правило №1.




© OSzone.net 2001-2012