Skip to content
This repository was archived by the owner on Dec 15, 2021. It is now read-only.

Add files via upload#1

Open
kukuruzvelt wants to merge 1 commit into
mainfrom
codereview
Open

Add files via upload#1
kukuruzvelt wants to merge 1 commit into
mainfrom
codereview

Conversation

@kukuruzvelt

Copy link
Copy Markdown
Owner

First commit

First commit
@Component
public class UserDAO {
final private String fileName = "jsonData.txt";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsonData.txt - Для json файлов принято расширение .json

final String stringPosts = restTemplate.getForObject("https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5", String.class);

return stringPosts;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getForObject это блокирующая функция, изза нее будут медленно работать запросы при нагрузках. Тут есть два варианта: либо сделать ее асинхронной, либо сделать отдельный тред, в котором раз в минуту (или раз во сколько он обновляется) спрашивать API приватбанка и сохранять результат. Первый способ лучше работает у API, которые часто обновляются, второй у API, которые обновляются в обозначенные промежутки времени.

boolean tf = false;
if (str.contains("{\"email\":\"" + user.getEmail() + "\",\"password\":\"" + user.getPassword() + "\"}")) {
tf = true;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше поменять на
boolean tf = str.contains(твое условие)
Название переменной tf скорее неудачное - без контекста не понятно, что она отображает
Опять же повторюсь, есть готовые библиотеки для работы с json, так что так проверять лучше не стоит.

fileWriter.write("[" + user.toString() + "]");
} else fileWriter.write("\b" + "," + user.toString() + "]");
}
fileWriter.close();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Записывать все данные в один файл нежелательно. При логине любого пользователя или проверке его существования как в функции check, придется итерироваться через весь файл, что дает сложность поиска O(n).

  2. Для работы с JSON файлами существуют готовые решения. Вручную это лучше не делать, так как это магнит для ошибок.


@Controller
@RequestMapping("/user")
public class FirstController {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Имя не отображает содержимое класса. "UserController", например, в данном случае смотрится гораздо лучше.

Comment on lines +17 to +21
@Autowired
private UserDAO userDAO;

@Autowired
private RateDAO rateDAO;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Внедрение зависимостей через поле - возможный вариант, но лучше отдать предпочтение внедрению через конструктор. Это, в частности, сильно упростит тестирование класса (например, внедрение моков)

Comment on lines +51 to +56
@GetMapping("/BTC")
public String BTCPage(Model model) {
double result = rateDAO.getRate();
model.addAttribute("result", result);
return "BTC";
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Даный эндпойнт сильно отличается от предыдущих по контексту. Заявка на нарушение SRP) Думаю, стоит вынести его в отдельный контроллер (напр. RateController, BitcoinController, ...)

Comment on lines +39 to +42
private String ccy;
private String base_ccy;
private double buy;
private double sale;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возможно тут подвела автогенерация кода (в частности, автогенерация геттеров\сеттеров), тем не мение, очень не привычно видеть переменные класса внизу, после объявления методов, а не внчале описания класса, что является классическим вариантом.

Comment on lines +3 to +6
public class User {
public void setPassword(String password) {
this.password = password;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Честно говоря, данный класс выглядит достаточно хаотично - слишком неупорядочены объявления членов класса. Классическая схема объявления членов класса: статические поля, переменные класса, конструкторы класса (начиная с базового), публичные методы, приватные методы, переопределённые методы класса Object (equals, hashCode, toString).

Comment on lines +25 to +42
private void parse() {
String stringPosts = this.getFromAPI();
int alreadyPassed = 0;

for (int i = 0; i < numberOfRatesInAPI; i++) {
int start = stringPosts.indexOf("{", alreadyPassed);
int end = stringPosts.indexOf("}", alreadyPassed);
alreadyPassed = end + 1;
String sub = stringPosts.substring(start, end + 1);
Gson g = new Gson();
Rate r = g.fromJson(sub, Rate.class);
rates[i] = r;
}
}


public double getRate() {
this.parse();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Снова отклонение от классического порядка объявление методов. Прослеживается интуитивный перенос особенностей С\С++ в Java). Т.е. сначала объявляется метод 1, потому что он вызывается в методе 2 (значит в момент нахождения в методе 2, компилятор уже должен располагать информацией о методе 1), при этом модификаторы доступа не берутся во внимание.
Тем не мение, такое ограничение на код Java не распространяется, и порядок объявления методов обычно обратный: публичный метод, а затем один за другим цепочка из приватных методов. Т.е. в данном случае более природным было бы следующее: getRate -> parse() -> getFromAPI()



private String getFromAPI() {
final RestTemplate restTemplate = new RestTemplate();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Думаю, тут также можно было бы задействовать механизмы DI.

public class UserDAO {
final private String fileName = "jsonData.txt";

public void save(User user) throws Exception {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пробрасывание базового исключения - bad practice. Как минимум - в данной ситуации можно пробросить более понятное исключение (в частности, IOException), что даст больше информации "наверху", где мы соответственно его попытаемся обработать.
Однако более предпочтительным вариантом, я считаю, должна быть обработка исключения прямо в этом методе.

П.С. Такая же позиция и по отношению к другим местам в коде с аналогичной ситуацией.

@Component
public class RateDAO {

final private int numberOfRatesInAPI = 4;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Подобные константы принято объявлять статическими, придерживаясь соответствующего именования, а именно UpperCasе, т.е:
private final static int NUMBER_OF_RATES_IN_API = 4;

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants