Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client #3

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open

Client #3

wants to merge 36 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Nov 12, 2020

Кирилл Верховский
АПО-12
Телеграмм: @Kirillazz
Клиентская часть взаимодействует с пользователем, получает от него команды, отправляет их на сервер. Потом получает ответ и отображает результат пользователю, обновляя данные.

@ghost ghost requested a review from leshiy1295 November 12, 2020 14:15
@ghost ghost assigned leshiy1295 Nov 12, 2020
Copy link
Collaborator

@leshiy1295 leshiy1295 left a comment

Choose a reason for hiding this comment

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

Продолжайте работу - ещё многое предстоит сделать, а времени - не так много

class UserInfo{
public:
UserInfo();
UserInfo(std::string& nm, std::string& psw);
Copy link
Collaborator

Choose a reason for hiding this comment

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

посмотрите доклад Джосаттиса про строчки

Comment on lines 29 to 30
std::vector<std::string> tags;
std::vector<std::string> snapshotPaths;
Copy link
Collaborator

Choose a reason for hiding this comment

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

использовать вектор в интерфейсе - плохая идея, т.к. при необходимости изменения придётся менять весь вызывающий код
инкапсулируйте и используйте PIMPL

std::vector<std::string> snapshotPaths;
};


Copy link
Collaborator

Choose a reason for hiding this comment

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

почему всё в одном файле?

class Request {
public:
virtual ReqExitStatus buildRequestFromInput(std::istream& s) = 0;
virtual std::string RequestToString() = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

виртуальный деструктор?

Comment on lines 89 to 96
requestPtr _LogInReq;
requestPtr _LogOutReq;
requestPtr _CreateRoomReq;
requestPtr _RemoveRoomReq;
requestPtr _AddLinkReq;
requestPtr _RemoveLinkReq;
requestPtr _LinkReq;
requestPtr _ArchiveLinkReq;
Copy link
Collaborator

Choose a reason for hiding this comment

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

переделайте через цепочку ответственностей - рассматривался паттерн на семинаре по тестированию

Room::Room(std::string& roomName, std::string& roomId) {}
void Room::addLink(std::string& newLink) {}
void Room::removeLink(std::string& linkName) {}
void Room::addParticipant(std::string& newPart) {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

хотелось бы хотя бы тестовую реализацию видеть...
в идеале - вызовы на уровне интерфейсов

RemoveRoomReq req;
RemoveRoomResp resp;

ASSERT_EQ(resp.doLogic(req, app), RESP_SUCCESS);
Copy link
Collaborator

Choose a reason for hiding this comment

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

такие тесты довольно мало смысла несут, т.к. ничего реально не проверяют - данные не инициализируются же ничем сейчас

@ghost
Copy link
Author

ghost commented Dec 10, 2020

Что использовал из STL:
vector - так как нужен был контейнер, который позволит избежать утечек памяти и облегчить работу с элементами.
vector::iterator - чтобы итерироваться по вектору.
shared_ptr - для использования указателей на реализицию в некоторых классах, а так же хранения объектов базовых классов.
string - для удобной работы со строками.

Copy link
Collaborator

@leshiy1295 leshiy1295 left a comment

Choose a reason for hiding this comment

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

Видно, что поздно приступили и не занимались проектированием архитектуры, а сразу же ринулись в разработку. Очень много сущностей не продумано, ответственность перемешана, и хуже всего реализовано главное меню со switch-case, который проник в разные компоненты системы.
Более того, судя по всему бОльшая часть логики пока ещё не реализована, поэтому необходимо в первую очередь интегрироваться с другими участниками команды, устранять ошибки и параллельно с этим приводить код к должному виду.
По поводу внешних зависимостей - я не знаю, что Вы собираетесь использовать. Если Qt, то текущие интерфейсы этого сделать не позволят, и придётся много чего переделывать. Также рекомендую внедрить систему конфигурационных файлов и подсистему логирования.

Comment on lines +36 to +59
#- name: test socket
# run: |
# cd client/build
# valgrind --leak-check=full ./test/socket_tests

#- name: test response
# run: |
# cd client/build
# valgrind --leak-check=full ./test/response_tests

#- name: test request
# run: |
# cd client/build
# valgrind --leak-check=full ./test/request_tests

#- name: test client
# run: |
# cd client/build
# valgrind --leak-check=full ./test/client_tests

#- name: test application
# run: |
# cd client/build
# valgrind --leak-check=full ./test/application_tests
Copy link
Collaborator

Choose a reason for hiding this comment

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

обычно CI запускает один скрипт, а какие тесты запускать/не запускать задаются конфигом и/или уже на уровне этого скрипта

#include <string>

#include "socket.hpp"
#include "socket.hpp"
Copy link
Collaborator

Choose a reason for hiding this comment

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

между первой и второй? :)


class Client {
public:
Client(const std::string& _host, int _port);
Copy link
Collaborator

Choose a reason for hiding this comment

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

уберите _

Client(const std::string& _host, int _port);
~Client() {}
void Connect();
void writeToServer(std::string& req);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Request - это куда более сложная структура, чем string
да и у Ваших коллег уже есть определённые структуры - согласуйте их с ними
если это GUI клиент, то непонятно, почему называется writeToServer...
интерфейс обычно работает с логикой экранов/кнопок и пр. Если у некоторых согласно поведению есть необходимость сходить за данными - они обращаются в презентер. Если у него нет состояния - он уже идёт в модель. Там может быть несколько слоёв. Например, кэш, локальная БД и если нигде уже нет - идёт на сервер. При переходе с уровня на уровень всегда можно оставить (и обычно так и делается) коллбэк, который сетит на все промежуточные слои пришедшие данные и возвращают их клиенту через публичный интерфейс

Link(std::string& name, std::string& url);
~Link();
const std::string GetLinkName();
void addSnapshot(std::string& path);
Copy link
Collaborator

Choose a reason for hiding this comment

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

если есть add, наверное, должен быть и remove?
но из интерфейса непонятно, а куда вообще снэпшот добавляется сейчас...

@@ -0,0 +1,6 @@
#include "userinfo.hpp"

UserInfo::UserInfo() : name(""), password("") {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

в дефолтные значения второго конструктора

Comment on lines 16 to 97
switch (key) {
case 1: {
inputStr += "1,";
std::cout << "Write name of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr;
std::cout << "Write host of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Host*" + appendStr;
}
break;
case 2: {
inputStr += "2,";
std::cout << "Write name of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr;
std::cout << "Write host of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Host*" + appendStr;
}
break;
case 3: {
inputStr += "3,";
/* std::cout << "Write name of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr + ",";
std::cout << "Write host of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Host*" + appendStr + "*Users*"; */
inputStr += "*Users*";
std::cout << "Write users" << std::endl;
while(!appendStr.empty()) {
std::cin >> appendStr;
inputStr += appendStr + ",";
}
}
break;
case 4: {
inputStr += "4,";
/* std::cout << "Write name of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr + ",";
std::cout << "Write host of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Host*" + appendStr + "*Users*"; */
inputStr += "*Users*";
std::cout << "Write users" << std::endl;
while(!appendStr.empty()) {
std::cin >> appendStr;
inputStr += appendStr + ",";
}
}
break;
case 5: {
inputStr += "5,";
std::cout << "Write name of link" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr + ",";
std::cout << "Write url of link" << std::endl;
std::cin >> appendStr;
inputStr += "*Url*" + appendStr;
break;
}
case 6: {
inputStr += "6,";
std::cout << "Write name of link" << std::endl;
inputStr += "*Name*";
std::cin >> inputStr;
}
case 7: {
inputStr += "7,";
std::cout << "Write name of link" << std::endl;
std::cin >> appendStr;
inputStr += "*Name*" + appendStr;
}
break;
case 0:
break;
default:
std::cout << "Wrong command. Try again" << std::endl;
break;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

следствие жути сщ switch/case...

Comment on lines 87 to 88
std::cout << "Write name of link" << std::endl;
std::cin >> appendStr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

перемешивание cin и cout - плохо
должен быть автомат, который разделит разные состояния друг от друга, и позволит код сделать чище

std::cout << "- 1.Create Room" << std::endl
<< "- 2.Remove Room" << std::endl
<< "- 3.Add users" << std::endl
<< "- 4.Remove users" << std::endl
Copy link
Collaborator

Choose a reason for hiding this comment

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

при добавлении новой команды в середину сломается вся программа
нужно генерировать описание из модели
возможно, с помощью XX Macro...

std::stringstream is;
ArchiveLinkReqHandler req;

// ASSERT_EQ(req.buildRequestFromInput(is), REQ_SUCCESS);
Copy link
Collaborator

Choose a reason for hiding this comment

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

пользы от таких тестов нет, к сожалению :(

@ghost
Copy link
Author

ghost commented Dec 24, 2020

Проверять с этого коммита.

Copy link
Collaborator

@leshiy1295 leshiy1295 left a comment

Choose a reason for hiding this comment

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

по ощущениям, добавилось много копипасты и "странных" решений
глобальных архитектурных проблем не решено
boost внедрён только на уровне main.cpp, что не считается эффективным и правильным

std::string logInInput();
std::string signUpInput();

#include "inputUtils.tpp"
Copy link
Collaborator

Choose a reason for hiding this comment

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

обычно это как раз-таки hpp...

@@ -0,0 +1,14 @@
#pragma once

#include <iostream>
Copy link
Collaborator

Choose a reason for hiding this comment

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

зачем?

Comment on lines +5 to +13
template<typename T, typename... Args>
void writeData(T* key) {
fillObject(key);
}

template<typename T, typename... Args>
void writeData(T* key, Args... args) {
fillObject(key);
writeData(args...);
Copy link
Collaborator

Choose a reason for hiding this comment

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

зачем выносить в отдельный файл?


template<typename T, typename... Args>
void writeData(T* key, Args... args) {
fillObject(key);
Copy link
Collaborator

Choose a reason for hiding this comment

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

writeData(key);

#include <iostream>

template<typename T, typename... Args>
void writeData(T* key) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

зачем?
можно было с помощью sizeof... проверить размер пакета в общем шаблоне

Comment on lines 29 to 46
template<typename T>
bool get_value(const char* key, T& value) {
if (boost::optional<T> v = pt.get_optional<T>(key)) {
value = *v;
return true;
} else {
return false;
}
}

bool get_value(const char* key, std::vector<std::string>& value) {
if (pt.get_child_optional(key)) {
BOOST_FOREACH (boost::property_tree::ptree::value_type& field, pt.get_child(key))
{
value.push_back(field.second.data());
}
return true;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

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

void Socket::Send(const std::string& str) {
std::string temp = "f" + str;
while(temp.size() != 400) {
temp.push_back('\x1A');
Copy link
Collaborator

Choose a reason for hiding this comment

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

хардкод

Comment on lines 46 to 49
for(auto it = tempStr.begin(); it != tempStr.end(); it++) {
if ((*it == ':' || *it == ',') /* && !special_block */) {
elements.push_back(element);
element = "";
Copy link
Collaborator

Choose a reason for hiding this comment

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

copy_if и inserter...

Comment on lines +125 to +127
for (auto it = std::find(vec.begin(), vec.end(), key) + 1; it != vec.end(); it++) {
inputVec->push_back(*it);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

copy_if...

std::cout << "Write host of room" << std::endl;
std::cin >> appendStr;
inputStr += "*Host*" + appendStr;
case DELETE_ROOM: {
Copy link
Collaborator

Choose a reason for hiding this comment

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

switch-case - это плохо в таких масштабах

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants