LINUX.ORG.RU

Что отличает юниора от более продвинутого

 ,


3

7

Начнем с такого вопроса: существует ли вообще такое понятие как «разработчик на C++ среднего уровня». Все знают, что есть junior и senior, но o промежуточном варианте я как-то не слышал.

Но, допустим, мы рассмотрим некий средний уровень. Что по-вашему должен уже знать/уметь миддл, чего может еще не знать юниор? Интересует только то, что непосредственно связано с языком, знания общего плана - это отдельная тема.

★★★★

Не бывает программистов. Есть кодеры и архитекторы. Когда ты это поймёшь автоматически станешь архитектором.

Если не поймёшь, то можешь надр@чить скилл до «кодер 80 уровня» (т.е. знать миллион библиотек наизусть)

anonymous ()
Ответ на: комментарий от UVV

и?

Там расписана структура процессора, есть блоки памяти.

О чем нам говорят циферки 16к*32 в структурной схеме процессора?

О чем нам говорит разрядность шины данных на УГО процесора?

Сколько бит в одном байте на этом процессоре?

Какой там будет sizeof(int)?

shkolnick-kun ★★ ()
Ответ на: комментарий от shkolnick-kun

Какую истину?
В каком месте?

Та константа обозначает количество битов в байте. То, что оно может принимать значение, отличное от 8, на других архитектурах, я не знал.

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

Вот тоже самое про two phase init и «всегда есть статические методы».

Думаю, что мысль ты понял. В плюсах, при большом желании, вместо конструктора иметь функцию, которая будет optional возвращать.

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

Думаю, что мысль ты понял.

Нет, не понял.

В плюсах, при большом желании, вместо конструктора иметь функцию, которая будет optional возвращать.

Покажите мне такую функцию, которая была бы аналогом простого конструктора для структуры вида:

struct user_info {
  std::string first_name_;
  std::string last_name_;
  std::string login_;
  std::string password_hash_;
};
и чтобы нехватка памяти при конструировании такой структуры не роняло все приложение. Ну так, просто чтобы оценить степень этого самого «большого желания».

eao197 ★★★★ ()
Ответ на: комментарий от eao197
namespace std {
using string = const char *;
}

struct user_info {
  std::string first_name_;
  std::string last_name_;
  std::string login_;
  std::string password_hash_;
};

int main() {
  user_info vasya = {
    .first_name_ = "Vasya",
    .last_name_ = "Ivanov",
    .login_ = "vasya42",
    .password_hash_ = "$1$O3JMY.Tw$AdLnLjQ/5jXF9.MTp3gHv/",
  };
}
anonymous ()
Ответ на: комментарий от eao197

Покажите мне такую функцию, которая была бы аналогом простого конструктора для структуры вида:

А зачем? Это имеет смысл если в конструкторе у нас нетривиальная логика в выбросом исключений. Цель такого как раз не использовать исключения для обработки ошибок, целиком оно их не заменяет. То есть, если в процессе создания user_info надо как-то валидировать или получать откуда-то поля, то выглядеть оно будет примерно следующим образом:

optional<user_info> create_user(...) {
    user_info res = { ... };

    if !is_valid(name) {
        return none;
    }

    ...

    return res;
}
Но да, в С++ такое выглядит непривычно и всюду такое пихать смысла не имеет. Опять же, если захочется так ошибку возвращать, то придётся variant использовать, что ешё менее удобно.

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

А зачем?

Затем, чтобы лучше понимать, во что вырождается подобное программирование.

Это имеет смысл если в конструкторе у нас нетривиальная логика в выбросом исключений.

Давайте так: покажите конструирование user_info без использования нормальных плюсовых конструкторов, тогда можно будет вернуться к разговору от тривиальности или нетривиальности логики.

А то когда речь заходит об отказе об исключениях, то люди быстро начинают съезжать на граничных условиях. Мол, если new не может выделить память, то нужно звать abort и ничего поделать нельзя.

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

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

Давайте так: покажите конструирование user_info без использования нормальных плюсовых конструкторов

Ну зачем ты в позу становишься? Отсутствие конструкторов я не обещал. Речь-то шла о том, что есть другие способа помимо убогой двух этапной инициализации.

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

Да просто я понял, что (пусть и несколько криво) пытался RazrFalcon донести. Он хочет «как в расте», где «типа конструкторы» явно возвращают значение или ошибку, но полного ухода от исключений (паники) там тоже нет (и не уверен, что можно это вменяемо сделать).

И предложенный вариант в контексте плюсов я не защищаю, просто хотел чтобы ясность появилась.

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

Ну зачем ты в позу становишься?

Хочу сохранить время. Пример кода лучше тысячи слов.

Речь-то шла о том, что есть другие способа помимо убогой двух этапной инициализации.

Можно на примере? Желательно на примере структуры user_info.

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

А то когда речь заходит об отказе об исключениях, то люди быстро начинают съезжать на граничных условиях.

Это не граничные условия, а реальность. В реальности нельзя заставить работать механизм отслеживания расхода памяти, которая существует в крестах. Конечно, вам выгодно верить в то, что всё непросто так, но толку? Реальность это не изменит.

Типичный пример эмулирующий работу типичной программы - создание в хипе множества объектов.

#include <string>
#include <vector>

int main() {
  
  std::vector<std::string> a, b, c, d;
  
  size_t s = 50 * 1024 * 1024 * 1024ul;
  
  for(size_t i = 0; i != s; ++i) {
    a.emplace_back("HelloHelloHelloHelloHelloHelloHelloHelloHelloHello");
    b.emplace_back("HelloHelloHelloHelloHelloHelloHelloHelloHelloHello");
    c.emplace_back("HelloHelloHelloHelloHelloHelloHelloHelloHelloHello");
    d.emplace_back("HelloHelloHelloHelloHelloHelloHelloHelloHelloHello");
  }
}

Результат прям идеален - типичное «не роняет приложение». И засунь туда хоть что - результат не изменится. А так, ваши инсинуации вокруг этой темы выглядят глупо.

А так да - делаем на примере кода. Я только за.

shielcody ()
Ответ на: комментарий от RazrFalcon

Тут дело не в языке. Люди спорят - не понимая нихрена ни в теме спора, ни вообще в чём-либо ещё. А по поводу языков - любой, который делает префолт. Такое я видел по моему даже в го.

Единственная причина которая спасает от падения кресты на простом заполнении вектора - это лак, а вернее эвристика в ядре. А рано или поздно это днище из ядра выпилят и что тогда начнётся. Поцаны уже потихоньку начинают пользоваться достижениями последних 20+лет и 10лет в массовом применении.

А по поводу крестов. По идее логика крестов подразумевает префолт, но почему его нет? А я тебе отвечу. Дело в том, что любой крестовик знает как расчёт каписити у вектора. И все варят в то, что какая-то там память выделяется и капасити отражает занимаемый объём памяти вектором.

Дак вот это не так. Вектор с какой угодно капасити занимает size памяти. Вместо с этим возникает проблема - оказывается то гениальное решение, что «как бэ» не жрёт память - на самом деле её нежрёт не потому, что оно настолько гениально, а потому что повезло.

И если в аллокатор добавить префолт - т.е. заставить new выделять столько памяти, сколько ты написал - потребление памяти твоими крестами вырастет на «50%». Такие дела.

А так получить в реальной программе бедаллок практически невозможно. На дефолтном аллокаторе ты физически его получить на блоках <4k не можешь, да и не на дефолтном скорее всего то же. На больших блоках тебе может фортануть в однопоточной среде и не фортанёт в многопоточной.

Не фортанёт в однопоточной среде тебе лишь из-за гениального решения с капасити, но тут ты словишь другие приключения. Если у тебя 32гб памяти ты попытаешься заполнить вектор до >16gb на крестах - у тебя ничего не выйдет. Ты свалишься в бедаллок.

Объясню подробнее ситуацию с «гениальным решением». Дело в том, что когда ты реалоцируешь память и начинаешь её заполнять - кто-то другой( в другом потоке/процессе) может её у тебя забрать. Дак вот это решение, которое не позволяет тебе использовать более 50%( т.е. 100% от того, что у тебя сейчас есть) твоей памяти уменьшает твои шансы на то, что у тебя кто-то отнимет эту память - т.к. ещё 16гигов свободные.

Единственная твоя возможность это сделать - изменить капасити руками, а это значит, что твоя защита ввиде 16гб исчезает. Поменяй ты капасити на 30гигов, то теперь другим процессам надо потратить всего 2+гига памяти, а не 16+, чтобы поставить раком систему.

Если ты думаешь, что это нерешаемая проблема, либо вообще какая-то проблема есть - это не так. Просто на неё забили в мире крестов и во всём остальном мире. 99% крестовиков о ней не знают, те кто знают - не верят. Им проще верить в то, что обработай они своё исключение - это им даст какие-то гарантии.

Ведь им не нужны гарантии - им нужен только трёп. А были бы нужны - они бы такую херню не несли. И жопа моя болит не из-за того, что крестовик чего-то не знает/понимает. А из-за того, что крестовик декларирует противоречащие реальности вещи. Выдавая свою бесполезную херню за решение, которое решает проблему. Он верить в неё может сколько угодно, но выдавать её за правду и требовать с других - это убого.-

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

Поэтому я и говорю, что исключения бесполезны. Всё аргументация обычно сводится к «а как обрабатывать OOM?». Да никак. Если я открываю виртуалку, и она у меня забирает больше памяти, чем у меня есть физически - то весь мой любимый линукс преспокойно падает (другие ОС тоже). И если я вдруг успею убить VM из TTY1, то я останусь с фактически нерабочими кедами, так как половина процессов преспокойно упало.

Но KDE на «убогом» Qt, как считают некоторые, а значит всё норм.

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

Поэтому я и говорю, что исключения бесполезны.

Бесполезны не исключения, а надежда на то, что крестовику что-то гарантирует бедалок. Ничего не гарантирует.

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

Исключения - это просто нелокальные переходы. Да в крестах из-за их крайне полезного раии они вызвают адскую жопаболь и проще забить чем пытаться свять на 100% правильно и безопасно. Но на это можно забить - я не ассоциирую язык только с его рантаймом.

Использовать в реальности исключения не особо приятнее кодов возврата - т.к. 3-4 либы и уже тебе надо городить свои прокси, которые раскидают все внешнее исключения по нужным категориям.

Если же забить на эти два пункта, то они не такие уж и плохие - мне нравится. Всё равно лучше ничего нет.

shielcody ()
Ответ на: комментарий от RazrFalcon

А как же Option/Optional и Result/Variant.

Ну их надо либо чекать, либо реплайсить значение. Мне обычно такое редко нужно. Мне проще либо строить логику так, где я могу всегда нажать роллбэк, либо прыгнуть в какой-нибудь основной обработчик. Либо заюзать исключение и забить вообще на проверки при написании кода.

Поэтому не могу сказать, что нашел много мест куда могу впихнуть Optional. Но может я особо не искал, либо у меня задачи неподходящие.

shielcody ()
Ответ на: комментарий от eao197

Можно на примере? Желательно на примере структуры user_info.

У меня «плохое предчувствие», что ты начнёшь цепляться к какой-то ерунде не относящейся к делу, но попробую. Все примеры схематичны.

Вариант 1, «традиционный»:

class user_info {
    std::string name_;
    ...

public:
    user_info(std::string name, ...)
        : name_(std::move(name))
        , ... {
        if !is_valid(name_) {
            throw ...;
        }
        ...
    }
};

Вариант 2, убогий (двухэтапная инициализация):

class user_info {
    // Если у полей нет специального состояния
    bool valid_;
    std::string name_;
    ...

public:
    user_info(std::string name, ...)
        : name_(std::move(name))
        , ...
    {}

    bool init() {
        if !is_valid(name_) {
            valid_ = false;
        }
        ...
        return valid_;
    }

    // Методы должны проверять "валидность"
};

Вариант 3 с использованием optional:

class user_info {
    // Если у полей нет специального состояния
    bool valid_;
    std::string name_;
    ...

    user_info(std::string name, ...)
        : name_(std::move(name))
        , ...
    {}

public:
    static optional<user_info> create(std::string name, ...) {
        user_info ui(std::move(name), ...);
        if !is_valid(ui.name_) {
            return none;
        }
        ...
        return ui;
    }
};

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

Ну их надо либо чекать, либо реплайсить значение

Кажется, обычно их надо мапать/флэтмапать

То, что в крестах std::optional из коробки ни того, ни другого не умеет — очередной большой косяк в дизайне, из-за которого им, вероятнее всего, пользоваться в силу неудобства будут полтора анонимуса.

С другой стороны, можно поступить по аналогии с тем, как делают скалисты: написать какой-нибудь rich_optional со всем нужным и не explicit конструктором или просто понаписать non-member функций, делающих то же самое, но у этих подходов тоже хватает недостатков.

Softwayer ()
Последнее исправление: Softwayer (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

У меня «плохое предчувствие», что ты начнёшь цепляться к какой-то ерунде не относящейся к делу, но попробую.

У меня «плохое предчувствие», что я не могу донести простую мысль. Попробую еще раз. Есть задача получить структуру с четырьмя std::string-ами внутри. Хотелось бы видеть ее решение без исключений с учетом того, что ошибка выделения памяти не приводит к немедленному вызову std::abort().

Ваш пример этого не демонстрирует, поскольку у вас уже есть готовые std::string-и, которые вы мувите во внутрь структуры. Тем самым вы не показываете самое интересное — как эти самые готовые стринги появляются. Тогда как в случае с исключениями пользователь мог бы просто писать что-то вроде:

user_info u{ "Vasya", "Pupkin", ... };

Вот мне и хочется посмотреть, как строчки «Vasya» и «Pupkin» будут помещаться внутрь user_info, когда у нас исключения запрещены в принципе.

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

когда у нас исключения запрещены в принципе.

Где и когда я это обещал? Собственно, пару сообщений назад писал следующее:

...«как в расте», где «типа конструкторы» явно возвращают значение или ошибку, но полного ухода от исключений (паники) там тоже нет...

Донести хотел только то, что в большинстве случаев от того, чтобы строить обработку ошибок на исключениях можно уйти.

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

Давайте я вам еще раз процитирую то, что говорил _вам_ чуть выше:

А то когда речь заходит об отказе об исключениях, то люди быстро начинают съезжать на граничных условиях. Мол, если new не может выделить память, то нужно звать abort и ничего поделать нельзя.

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

Разговор с другим человеком шел про неиспользование исключений вообще. Но тут появляетесь вы, пытаетесь мне что-то показать, но приходите к тому, что «Где и когда я это обещал?» Не обещали, так не встревайте.

что в большинстве случаев от того, чтобы строить обработку ошибок на исключениях можно уйти.

Многие современные C++ программисты, как показывает практика, даже отдаленно не представляют себе, в каком количестве мест могут возникать ошибки. И насколько наличие исключений делает их код проще, даже когда они думают, что исключения не используют.

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

Не обещали, так не встревайте.

(Изначально) я отвечал на конкретную ветку про конструкторы. И в контексте этого мои утверждения в силе. Ну да, с оговоркой про bad_alloc, то есть про весьма особенный случай.

И да, ты пару раз доказывал пользу обработки этого исключения на примерe, когда оно обрабатывалось, по сути, ошибочно. Так себе, преимущество, как по мне. Предугадываю аргумент про то, что «работающий» софт лучше правильного.

И насколько наличие исключений делает их код проще, даже когда они думают, что исключения не используют.

И что в этом хорошего? Если кто-то и не подозревает, что делает ерунду, то может лучше бы он это видел? Может всё-таки собрался бы написать код пусть более сложный, но с обработкой потенциальных ошибок. Другое дело, что в плюсах невозможно отличить сознательное это решение или нет.

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

Я напомню сообщение, на которое вы ответили: www.linux.org.ru/forum/development/13394940?cid=13396099

Вы не пояснили мне точку зрения RazrFalcon. И не показали, какие вменяемые альтернативы могут быть у two phase commit в ситуации, когда исключения вообще запрещены.

Т.е. для меня вы не сказали ничего полезного.

И что в этом хорошего?

Программирование упрощается. Кто-нибудь хочет задумываться над тем, как контролировать ошибки в чем-то подобном:

auto some_complex_function(const std::string & value, ...) {
  auto f = std::async(std::launch::async, [value] { ... });
  ...
  return f;
}
?

Если хочет, то пусть перепишет на кодах возврата.

Если кто-то и не подозревает, что делает ерунду, то может лучше бы он это видел?

Давайте не будем сбиваться на бинарное мышление и на деление только на «ерунду» и «не ерунду». Когда у кого-то есть код вида:

void f(std::ostream & log) {
  log << "starting";
  ...
  log << "finishing";
}
Делает ли он ерунду используя operator<< и не задумываясь о том, что вызов operator<< может привести к возникновению ошибки?

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

Я напомню сообщение, на которое вы ответили: www.linux.org.ru/forum/development/13394940?cid=13396099

Помню. И?

Т.е. для меня вы не сказали ничего полезного.

Я попытался несколько раз и несколько раз подчеркнул, что речь не идёт об «запрете исключений вообще». Особенно забавно это смотрится вместе с дальнейшими разговорами о бинарном мышлении.

Касательно остального: меня более-менее устраивает текущее положение вещей В С++. Только это не мешает размышлять о том можно ли сделать лучше, причём как в контексте «чистой теории», так и в контексте новых стандартов или других языков.

Делает ли он ерунду используя operator<< и не задумываясь о том, что вызов operator<< может привести к возникновению ошибки?

Если именно не задумывается и это не хелло ворлд, то да, делает ерунду. Всё-таки хочется думать, что опытные и вменяемые люди понимают, что ошибка может быть и сознательно её игнорируют. Это опять к разговору о невозможности (удобно) показать намерения.

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

Помню. И?

И вот: «для меня вы не сказали ничего полезного»

Я попытался несколько раз и несколько раз подчеркнул, что речь не идёт об «запрете исключений вообще».

Еще раз говорю: мне интересны ответы на вопросы в ситуации когда исключения запрещены вообще. Вы напрасно влезли с попытками рассказать что-то для другой ситуации.

Если именно не задумывается и это не хелло ворлд, то да, делает ерунду.

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

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

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

К счастью, на форуме «влезать» может кто угодно и с чем угодно.

Ведь в случае присутствия исключений здесь нет проблем.

Не факт. Если человек не задумывает об исключениях и предполагает, что запись в лог всегда успешна, то его будет ждать сюрприз. Который может быть ещё интереснее, если catch отсутствует в принципе. В итоге данные запросто могут оказаться в несогласованном состоянии. Само наличие исключений тут ничего магическим образом не исправит.

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

К счастью, на форуме «влезать» может кто угодно и с чем угодно.

Ну вот вы влезли и кому это пошло на пользу?

Если человек не задумывает об исключениях и предполагает, что запись в лог всегда успешна

Да, если человеку дать коды возврата вместо исключений, то он, конечно же, сразу начнет задумываться, может ли запись в лог вернуть ошибку или нет. А если может, то, конечно же, не менее сразу же начнет проверять все записи в лог. Более того, он, конечно же, сразу же начнет писать свой код так, чтобы сохранялись инварианты и данные оказывались в согласованном состоянии даже при преждевременном return err.

Давайте выясним, про кого мы говорим: про абстрактного нормального программиста или про абстрактного Джамшута. Поскольку если про Джамшута, то он будет говнокодить и с исключениями, и без.

А если про нормального, который задумывается и о наличии ошибок, и о консистентности данных, и о преждевременных return-ах, то в C++ без исключений такому разработчику придется писать гораздо больше кода. И код этот будет не так уж надежен, поскольку C++ не бьет по рукам, если забыть написать какую-то проверку.

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

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

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

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

Смотря как оно будет выглядеть. Если компилятор будет ругаться на то, что «код возврата» игнорируется, то слегка задуматься придётся.

Ответа на вопрос как это удобно сделать для операторов у меня нет.

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

Даже «нормальный» может о чём-то забыть. Речь о том, что язык никак не подстрахует, а так же о том, что при чтении кода не всегда понятно забывчивость это или сознательное решение.

Тезис про полезность статических методов вместо конструкторов в случае запрета исключений мне пока никто так и не раскрыл.

Это потому, что ты не хочешь слушать.

Альтернативный ответ: нет никакой пользы.

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

Если компилятор будет ругаться на то, что «код возврата» игнорируется, то слегка задуматься придётся.

Ну вот в C++17 может начать ругаться, если разработчики библиотек будут атрибут nodiscard правильно расставлять. Тогда и будем посмотреть. Пока что безопаснее отталкиваться от того, что исключение может выскочить практически отовсюду.

Это потому, что ты не хочешь слушать.

Это потому, что тот, кому вопрос бы изначально задан, слился. А вы уходите в сторону «Где и когда я это обещал?»

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

А вы уходите в сторону «Где и когда я это обещал?»

Дело в том, что с большой вероятностью, я правильно понял, что хотел сказать RazrFalcon: ему (как и мне) симпатичен раст, но там нет никакого решения для полного отказа от «исключений». А вот обработку ошибок принято строить на «кодах возврата» и вместо «конструкторов» используются как раз «статические функции».

Вот и всё, что я хотел сказать. Но да, это никак не решает тех проблем, которые ты предлагаешь решать.

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

Дело в том, что с большой вероятностью, я правильно понял, что хотел сказать RazrFalcon: ему (как и мне) симпатичен раст

Я, конечно, понимаю, что вам с RazrFalcon симпатичен Rust. Но, блин, как же уже задолбали отсылки на Rust в контексте разговора про C++. Нельзя перенести из Rust-а практики в C++, как и наоборот. Все, хватит лохматить бабушку.

А если на вопрос, как упростить жизнь в C++ следует очередной кивок в сторону Rust-а, то мне это не интересно. И, полагаю, это совсем не конструктивно.

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

Нельзя перенести из Rust-а практики в C++, как и наоборот.

Да ладно? Прямо так всегда и во всех случаях?

Кстати, «нельзя» и «нет смысла» тоже разные вещи.

DarkEld3r ★★★★ ()
Последнее исправление: DarkEld3r (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

Да ладно? Прямо так всегда и во всех случаях?

Говорят, что нельзя говорить, что нельзя одевать штаны через голову.

Может быть это даже и справедливо. Но вовсе не означает разумность таких действий.

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

О да. Есть плебс и илитка.

А тенденция такая: кто не умеет писать код, тот лезет в архитекторы. А совсем далёкие от этого люди лезут в руководители. Так что если не осилил ничего кроме бубльсорта, то счастливого пути в архитекторы.

dzidzitop ()