Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
1

Как избежать дублирования кода при написании константного и не константного метода?

28.02.2022, 15:43. Показов 2433. Ответов 36
Метки c++ (Все метки)

Author24 — интернет-сервис помощи студентам
Есть класс Buffer, который содержит метод forBounds, который в качестве параметров принимает вспомогательный класс Bounds и шаблонный элемент _Func, который должен быть лямбда-функцией, в которой описывается логика. В общем, сам метод чем-то напоминаем функцию std::for_each. Проблема заключается в том, что мне нужно как-то сделать два метода const и не const версию. Дублировать код и писать макросы как-то не хочется.

Есть ли способ, как можно сделать два одинаковых по коду метода, но так, чтобы один был const, а другой нет, но при этом избежать дублирования?
C++
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
26
27
28
29
30
31
32
33
34
template<typename _T>
template<typename _Func>
inline bool Buffer<_T>::forBounds(const Bounds& bounds, const _Func& func) const
{
    if (!getBounds().isContain(bounds))
    {
        CERR_ERROR(STR_ERROR_VIOLATION_OF_BUFFER_BOUNDS)
        return false;
    }
    const size_t start_index = bounds.getStartCell().toIndex(m_dimension);
    const size_t finish_index = bounds.getFinishCell().toIndex(m_dimension);
    const size_t width = bounds.getWidth();
    const size_t step = getNumberOfColumns() - width;
    size_t current_col = 1;
    for (size_t i = start_index; i <= finish_index; i++)
    {
        func(at(i));
        if (current_col % width == 0)
        {
            current_col = 1;
            i += step;
        }
        else
            current_col++;
    }
    return true;
}
 
template<typename _T>
template<typename _Func>
inline bool Buffer<_T>::forBounds(const Bounds& bounds, const _Func& func)
{
    //Надо что-то сделать, чтобы не дублировать код.
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.02.2022, 15:43
Ответы с готовыми решениями:

Возврат константного значение из функции/метода
Здравствуйте подскажите пожалуйста как из функции или метода вернуть константное значение? что бы...

Выполнение метода в зависимости от константного свойства
class Z { private: const int num; public: Z(int val): num(val){} template&lt;int...

Как избежать дублирования кода при использовании virtual функций?
Здравствуйте. Есть Класс Студент_А и Студент_Б. В каждом есть поле private содержащее string name....

Избежать дублирования проверок при выполнении метода
Предположим, у банка есть метод который осуществляет перевод денег со счета на счет. В нем есть...

36
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.03.2022, 01:21 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от John Prick Посмотреть сообщение
тип this в таком методе - const Bounds * const.
ты ошибаешься.

this не может быть const t,
поскольку ключевое слово обозначает prvalue,
для которого отбрасывается верхний const.

пример:
https://rextester.com/IRRMSL71179


C++
1
2
3
4
//  warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const int* const ptr();
 
int main(){}
Цитата Сообщение от Аким2020 Посмотреть сообщение
Если есть идеи лучше, пожалуйста, скажите мне.
идея получше заключается в том,
что бы ты привел минимальный пример-иллюстрацию того,
чего ты хочешь.

и когда я пишу: "минимальный пример-иллюстрацию",
то имею ввиду полноценную программу,
которая включает в себя функцию main,
и все необходимые детали,
а не огрызки.

Цитата Сообщение от Аким2020 Посмотреть сообщение
_template_params_
UB
0
фрилансер
5859 / 5398 / 1104
Регистрация: 11.10.2019
Сообщений: 14,412
01.03.2022, 06:30 22
Аким2020, захват в лямбде ссылки или указателя на буфер сильно всё упростит, в том числе и отладку.
0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 10:23  [ТС] 23
hoggy,
C++
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
26
27
28
int main()
{
    const Buffer<int> buffer_const =
    {
        {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}
    };
    auto buffer_non_const = buffer_const;
 
    buffer_const.forEach([](int& element)// Ошибка т.к. лямбда может изменить состояние буффера, а буффер константный.
        {
            std::cout << element << std::endl;
        }
    );
    buffer_const.forEach([](const int& element)// Нет ошибки т.к. лямбда не может менять состояние буффера.
        {
            std::cout << element << std::endl;
        }
    );
    buffer_non_const.forEach([](int& element)// Нет ошибки т.к. буффер не конст.
        {
            std::cout << element << std::endl;
        }
    );
}
Вот что я хочу. Что бы в случае, если лямбда, способная изменять состояние буффера передавалась в метод константного объекта, происходила ошибка, а если бы передавалась в не конст. объект ошибки не было и лямбда могла бы изменять состояние объекта.
0
SmallEvil
01.03.2022, 10:37
  #24

Не по теме:

Аким2020, почему то мне кажется, что вы воюете с ветряными мельницами...

0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 10:41  [ТС] 25
SmallEvil, возможно...
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
01.03.2022, 11:17 26
Цитата Сообщение от Аким2020 Посмотреть сообщение
Что бы в случае, если лямбда, способная изменять состояние буффера передавалась в метод константного объекта, происходила ошибка, а если бы передавалась в не конст. объект ошибки не было и лямбда могла бы изменять состояние объекта.
C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
template <typename T>
class Buffer {
public:
....................
    
    T const & front() const {
        return .............
    }
    T & front() {
        return ............
    }        
    template <typename Func>
    auto forEach(Func f) const -> std::void_t<decltype(f(this->front()))> {
        ...............
    }
    template <typename Func>
    auto forEach(Func f) -> std::void_t<decltype(f(this->front()))> {
        .............      
    }
    
private:    
    .................
};
 
 
 
 
int main()
{
    const Buffer<int> buffer_const =
    {
        {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}
    };
    
    auto buffer_non_const = buffer_const;
 
    buffer_const.forEach([](int & element)// Ошибка т.к. лямбда может изменить состояние буффера, а буффер константный.
        {
            std::cout << element << std::endl;
        }
    );
    buffer_const.forEach([](const int& element)// Нет ошибки т.к. лямбда не может менять состояние буффера.
        {
            std::cout << element << std::endl;
        }
    );
    buffer_non_const.forEach([](int& element)// Нет ошибки т.к. буффер не конст.
        {
            std::cout << element << std::endl;
        }
    );
}
Добавлено через 2 минуты
Или то же самое через концепты в C++20.
0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 11:50  [ТС] 27
DrOffset, но мне же все равно тут придется писать два одинаковых определения метода forEach. Для const и non-const.
C++
1
2
3
4
5
6
7
8
    template <typename Func>
    auto forEach(Func f) const -> std::void_t<decltype(f(this->front()))> {
        ...............
    }
    template <typename Func>
    auto forEach(Func f) -> std::void_t<decltype(f(this->front()))> {
        .............      
    }
0
3719 / 2648 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
01.03.2022, 11:59 28
Цитата Сообщение от DrOffset Посмотреть сообщение
T const & front() const {
        return .............
    }
    T & front() {
        return ............
    }
Да, это первое что приходит в голову, но проблему изначального вопроса не решает.
Вся суть константности, инкапсуляции не в том что бы зделать код "деревянным" или "железобетонным",
но как раз наоборот.

Аким2020, в Вашем случае, нет в необходимости в константном методе вообще.
Поэтому я долго не мог понять сути вопроса, проблемы.
Если ваш метод, изменяет данные, то он не может быть в априори константным.
При попытке вызова такой функции от константного объекта, получите compile time error.
В чем вопрос ?

Добавлено через 3 минуты
Или если метод не изменяет данные, то делайте его ТОЛЬКО константным.
0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 12:19  [ТС] 29
SmallEvil, const метод нужен для обхода коллекции без изменения самой коллекции. Сейчас попробую объяснить еще раз более подробно.

Вот то, как это работает с дублированием кода. То, как я хотел бы, чтоб это работало.

C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <initializer_list>
#include <vector>
#include <algorithm>
 
template<typename _T>
class Buffer
{
private:
 
    std::vector<_T> m_vector;
 
public:
 
    Buffer(const std::initializer_list<_T>& init_list) :
        m_vector(init_list)
    {
    }
 
    template<typename _Func>
    void forEach(const _Func& func) const
    {
        std::for_each(m_vector.begin(), m_vector.end(), func);
    }
 
    template<typename _Func>
    void forEach(const _Func& func)
    {
        //Дублирование кода.
        //Тут не критично, но в моем проекте тут спяртана довольно-таки крупная логика.
        std::for_each(m_vector.begin(), m_vector.end(), func);
    }
};
 
int main()
{
 
    const Buffer<int> const_buffer = { 1,2,3,4,5 };
    //Этот метод нужен для обхода коллекции без изменения буффера. Например, для подсчета четных значений.
    //Тут будет ошибка, потому что в лябмду передана ссылка на элемент буффера.
    const_buffer.forEach([](int& el)
        {
        }
    ); std::cout << std::endl;
 
 
    //А тут ошибки не будет, потому что лямбда принимает const элемент и изменить состояние буффера не сможет.
    const_buffer.forEach([](const int& el)
        {
        }
    ); std::cout << std::endl;
 
 
    auto non_const_buffer = const_buffer;
    //Этот метод нужен для обхода коллекции с возможностью изменения буффера. Например, для замены четныхх значний - цифрой 0.
    //Тут ошибки не будет, потому что буффер не конст.
    non_const_buffer.forEach([](int& el)
        {
        }
    ); std::cout << std::endl;
 
 
 
}

А теперь я пробую убрать дублирование кода, вызовом const метода из non-const, как мне предлагали ранее.

C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template<typename _T>
class Buffer
{
private:
 
    std::vector<_T> m_vector;
 
public:
 
    Buffer(const std::initializer_list<_T>& init_list) :
        m_vector(init_list)
    {
    }
 
    template<typename _Func>
    void forEach(const _Func& func) const
    {
        std::for_each(m_vector.begin(), m_vector.end(), func);
    }
 
    template<typename _Func>
    void forEach(const _Func& func)
    {
        return std::as_const(*this).forEach(func);
    }
};
 
int main()
{
 
    Buffer<int> non_const_buffer = { 1,2,3,4,5 };
    //Будет ошибка, т.к. я вызову const метод и передам в него лямбду способную изменить состояние буффера
    //То есть, вызывая non-const метод для non-const буффера, я вызову const метод.
    non_const_buffer.forEach([](int& el)
        {
        }
    ); std::cout << std::endl;
 
 
 
}
Вопрос в том, как убрать дублирование и сохранить ту логику, которую я пытаюсь заложить? Я воспользовался макросом, который вы могли увидеть ранее, но такой способ решения мне не очень нравится.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
01.03.2022, 12:21 30
Аким2020,
C++
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
26
27
28
29
30
31
template <typename T>
class Buffer {
public:
    ..............
        
    T const & front() const {
        return .....
    }
    T & front() {
        return ....
    }        
    template <typename Func>
    auto forEach(Func f) const -> std::void_t<decltype(f(this->front()))> {
        const_cast<Buffer*>(this)->forEachImpl(f);
    }
    template <typename Func>
    auto forEach(Func f) -> std::void_t<decltype(f(this->front()))> {
        forEachImpl(f);    
    }
    
private:
    template <typename Func>
    void forEachImpl(Func f) {
        for(auto & v : m_buf) {
            f(v);    
        }
    }
    
private:    
    .... m_buf;
};
0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 12:35  [ТС] 31
SmallEvil,
Цитата Сообщение от SmallEvil Посмотреть сообщение
Или если метод не изменяет данные, то делайте его ТОЛЬКО константным.
в этом-то и проблема. Я пытаюсь сделать один метод, который бы можно было использоваться для обхода без изменений, а другой, который бы точно также обходил коллекцию, но с возможностью изменения.

Возможно, для метода, который обходит каждый элемент коллекции - это выглядит глупо, но в моем класс Buffer, который в заглавии этой темы, метод forBounds прячет в себе некую логику.

Добавлено через 10 минут
DrOffset, вот это, вроде, работает, как надо. Сейчас разберусь до конца и скажу точно.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
01.03.2022, 12:59 32
Цитата Сообщение от Аким2020 Посмотреть сообщение
вот это, вроде, работает, как надо.
Это ничем не отличается от того, что было до этого, за исключением раскрытия тел методов.
Конкретно этот прием с кастом можно рассмотреть в книге Мейерса (точно не помню в какой, кажется в Эффективное использование C++ - 55 советов). Это не очень распространенный прием и довольно спорный, и в некоторых случаях его использование небезопасно, но если вы приняли меры предосторожности, то вполне допустимый.

Можно и без кастов обойтись, если сделать шаблонную функцию, или воспользоваться стандартной:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <typename T>
class Buffer {
public:
    T const & front() const { return m_buf.front(); }
    T & front() {  return m_buf.front(); }   
    
    template <typename Func>
    auto forEach(Func f) const -> std::void_t<decltype(f(this->front()))> {
        std::for_each(m_buf.begin(), m_buf.end(), f);
    }
    template <typename Func>
    auto forEach(Func f) -> std::void_t<decltype(f(this->front()))> {
        std::for_each(m_buf.begin(), m_buf.end(), f);
    }
 
private:
    
private:    
    std::vector<T> m_buf;
};
Вот здесь, например, нет никакого дублирования кода.

Добавлено через 10 минут

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
кажется в Эффективное использование C++ - 55 советов
Да, на 37 странице в русском издании.

0
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 13:23  [ТС] 33
DrOffset, возвращаемый тип auto. Не подскажите, как можно указать, например, bool?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
01.03.2022, 13:27 34
Лучший ответ Сообщение было отмечено Аким2020 как решение

Решение

Цитата Сообщение от Аким2020 Посмотреть сообщение
возвращаемый тип auto.
Возвращаемый тип void, если что

Цитата Сообщение от Аким2020 Посмотреть сообщение
Не подскажите, как можно указать, например, bool?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template <typename T>
class Buffer {
public:
    T const & front() const { return m_buf.front(); }
    T & front() {  return m_buf.front(); }   
    
    template <typename Func>
    auto forEach(Func f) const -> decltype(f(this->front()), bool()) {
        std::for_each(m_buf.begin(), m_buf.end(), f);
        return true;
    }
    template <typename Func>
    auto forEach(Func f) -> decltype(f(this->front()), bool()) {
        std::for_each(m_buf.begin(), m_buf.end(), f);
        return true;
    }
 
private:
    
private:    
    std::vector<T> m_buf;
};
PS. если у вас доступен C++20, то пользуйтесь концептами вместо SFINAE.
1
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 13:43  [ТС] 35
DrOffset, ну, вы гений получается.
Все работает даже лучше, чем я себе представлял. Спасибо вам огромное, а-то я уже с макросом думал смириться(
0
3719 / 2648 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
01.03.2022, 13:49 36
Лучший ответ Сообщение было отмечено Аким2020 как решение

Решение

Цитата Сообщение от Аким2020 Посмотреть сообщение
Как избежать дублирования кода при написании константного и не константного метода?
Не оно ?
C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <initializer_list>
#include <vector>
#include <algorithm>
 
template<typename _T>
class Buffer
{
private:
 
    std::vector<_T> m_vector;
    template<typename _Func, typename Class>
    void static forEach(Class& this_, const _Func& func)
    {
        std::for_each(this_.m_vector.begin(), this_.m_vector.end(), func);
    } 
public:
 
    Buffer(const std::initializer_list<_T>& init_list) :
        m_vector(init_list)
    {
    }
 
    template<typename _Func>
    void forEach(const _Func& func)
    {
        Buffer::forEach(*this, func);
    }
    template<typename _Func>
    void forEach(const _Func& func) const
    {
        Buffer::forEach(*this, func);
    }
};
 
int main()
{
 
    const Buffer<int> const_buffer = { 1,2,3,4,5 };
    //Этот метод нужен для обхода коллекции без изменения буффера. Например, для подсчета четных значений.
    //Тут будет ошибка, потому что в лябмду передана ссылка на элемент буффера.
    /*
    const_buffer.forEach([](int& el)  // error "int& el" , must be const
        {
            // ++el; //error
            std::cout << el << ' ';
        }
    ); 
    */
    std::cout << std::endl;
    // const_buffer.forEach([](const int& el)  // ok
    const_buffer.forEach([](auto& el) // ok
        {
            // ++el; //error
            std::cout << el << ' ';
        }
    ); 
    std::cout << std::endl;
 
    Buffer<int> non_const_buffer = const_buffer;
    //Этот метод нужен для обхода коллекции с возможностью изменения буффера. Например, для замены четныхх значний - цифрой 0.
    //Тут ошибки не будет, потому что буффер не конст.
    non_const_buffer.forEach([](int& el)
        {
            ++el; // Ok
            std::cout << el << ' ';
        }
    ); std::cout << std::endl;
 
}
1
6 / 5 / 1
Регистрация: 05.10.2020
Сообщений: 122
01.03.2022, 15:03  [ТС] 37
SmallEvil, да, это тоже отлично подходит и синтаксис более дружелюбный.
0
01.03.2022, 15:03
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.03.2022, 15:03
Помогаю со студенческими работами здесь

Как избежать дублирования кода?
Приветствую Вас уважаемые форумчане! Хочу обратиться к Вам за помощью. Возникли огромные пробелы...

Как избежать дублирования кода в Си
Допустим, есть такие структуры данных: enum Color{ Red, Blue, Black, White };...

Как избежать дублирования кода? Наследование
Здравствуйте. У меня следующая проблема: Есть несколько классов: A, B, C. Они наследуются от...

Ошибка при выводе константного значения С++
Всем привет! Столкнулся с проблемкой, выводит вот такую ошибку. Ошибка C2679 бинарный &quot;&lt;&lt;&quot;: не...

Ошибка при обращении к методу константного объекта
Есть некий класс, в нем есть метод const size_t Length(); пишу оператор сложения Class&amp; operator...

Усечение константного значения при присвоении значений объектам структуры
Здравствуйте! Есть вот такой код: #include &lt;iostream&gt; using namespace std; struct date {...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Как работать с ветками (branch) в Git
InfoMaster 17.01.2025
Система контроля версий Git произвела революцию в процессе разработки программного обеспечения, предоставив разработчикам мощный инструмент для управления изменениями в коде. Одной из наиболее важных. . .
Как откатить последние коммиты в Git
InfoMaster 17.01.2025
Система контроля версий Git стала неотъемлемой частью современной разработки программного обеспечения, предоставляя разработчикам мощные инструменты для управления изменениями в коде. Одним из. . .
Что такое boilerplate и scaffold, чем они отличаются
InfoMaster 17.01.2025
В современном мире разработки программного обеспечения эффективность и скорость создания качественного кода играют crucial роль в успехе проектов. Разработчики постоянно ищут способы оптимизировать. . .
Чем отличаются ссылки и указатели в С++
InfoMaster 17.01.2025
В современном программировании на C++ эффективная работа с памятью является ключевым аспектом разработки качественного программного обеспечения. Указатели и ссылки представляют собой два. . .
В чем разница между PUT и POST
InfoMaster 17.01.2025
В современной веб-разработке правильное использование HTTP-методов играет ключевую роль в создании надежных и эффективных API-интерфейсов. Протокол HTTP прошел долгий путь развития с момента своего. . .
DTO, POCO и Value Object: что это такое, когда и как использовать
InfoMaster 17.01.2025
Введение в паттерны передачи данных В современной разработке программного обеспечения эффективное управление данными и их передача между различными слоями приложения являются ключевыми аспектами. . .
Что такое pull request в Git
InfoMaster 17.01.2025
В современной разработке программного обеспечения pull request в Git представляет собой ключевой механизм для эффективного взаимодействия между разработчиками при работе над общим кодом проекта. По. . .
Как вернуться к предыдущему коммиту в Git
InfoMaster 17.01.2025
Система контроля версий Git представляет собой мощный инструмент для управления изменениями в программном коде, который позволяет разработчикам эффективно отслеживать и контролировать историю. . .
Что такое паттерны программировани­я и проектирования
InfoMaster 17.01.2025
Роль паттернов в современной разработке программного обеспечения В современном мире разработки программного обеспечения паттерны проектирования стали неотъемлемой частью профессионального подхода. . .
Как добавить конструктор Яндекс Карт на сайт
InfoMaster 17.01.2025
Введение в API Яндекс Карт В современной веб-разработке интеграция картографических сервисов стала неотъемлемой частью многих проектов. API Яндекс Карт представляет собой мощный инструмент для. . .
Что такое javascript:void­­(0) и зачем это нужно
InfoMaster 17.01.2025
Когда вы сталкиваетесь с веб-разработкой, особенно с использованием JavaScript, одной из директив, которая часто встречается, является javascript:void(0). Это выражение вызывает интерес из-за своей. . .
Что такое оркестрация и хореография микросервисов
InfoMaster 17.01.2025
Введение в оркестрацию и хореографию микросервисов В современном мире разработки программного обеспечения микросервисная архитектура стала ключевым подходом к созданию масштабируемых и гибких. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru