• Как перестать говнокодить и принимать неверные архитектурные решения?

    miraage
    @miraage
    Старый прогер
    как писать поддерживаемый код?

    Если уж очень коротко, то соблюдать SOLID/GRASP. Мне понравился твит одного из авторов React Router:
    https://twitter.com/mjackson/status/1171524189850701825

    Most common mistake software developers make: putting stuff in the wrong place. Coupling responsibilities and concepts that should be kept separate.
    For me, this is 95% of software development. Just figuring out *where* things belong.


    Что гуглить, что учить?

    Фундаментальные знания, вроде вышеупомянутых SOLID/GRASP, паттерны (не только классические паттерны, но и вообще, общеизвестные решения определённых задач), базовые структуры данных. Фреймворки/библиотеки всегда будут приходить/уходить, что-то будет забываться. А фундаментальные знания всегда актуальны.

    Может литературу какую почитать посоветуете?

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

    Можно ли себя называть миддлом, если твой код говно?

    Не пытайтесь себя оценить. В каждой компании свои понятия миддла. А если кто-то 35 лет на лиспе кодил, а потом прыгнет на Angular - кто он, джун или сеньор?
    И, да, все мы в какой-то степени пишем говнокод. Если кто-то Вам доказывает, что он пишет супер чистый код - не слушайте.

    И ответ на главный вопрос.
    Как перестать говнокодить и принимать неверные архитектурные решения?

    Это невозможно. Все проекты, которые чуток сложнее CRUD-ов, рано или поздно обрастают говнокодом. Никто не пишет идеальный код. Код должен работать и решать проблемы бизнеса.
    Ответ написан
    6 комментариев
  • Что мы будем видеть в иллюминаторе ракеты, движущейся с околосветовыми скоростями, включая скорость света?

    samodum
    @samodum
    Какой вопрос - такой и ответ
    Фотон движется со скоростью света и времени для него нет, не существует. Все процессы, которые могли бы происходить внутри фотона, остановлены. Даже для фотона, родившегося 13 миллиардов лет назад, времени не существовало. Он родился давно и умер - для него это мгновение, хотя и прошли миллиарды лет. Он ничего не видел.
    Так же и мы будем как фотон - для нас время остановится, мы просто замрём на месте, видеть ничего не будем и делать ничего не сможем.
    Ответ написан
    2 комментария
  • Как вы проектируете классы в ООП и их взаимодействие?

    @xfg
    В PHP сообществе вообще не развиты вопросы проектирования и архитектуры. Большинство лепит, что придумает. PHP изначально родился для примитивных homepage, вобрал в себя всю несерьезность, низкий порог входа и как следствие довольно слабое комьюнити, что часто становится объектом для шуток.

    Искать ответы на вопросы проектирования и архитектуры нужно в Java. Например там почти каждый с самых азов слышал о де факто ставшей стандартом слоистой архитектуре, она же layered architecture, она же n-tier architecture и видел изображение похожее на это
    main-qimg-91d7188a63a833488f92239028d0ae
    Из которой нужно понять, что всю программу можно разделить на несколько слоев и зависимость между слоями должна быть направлена сверху вниз, но не наоборот. Таким образом, например фреймворк может быть инкапсулирован в presentation слой и в любой момент безболезненно заменен на другой, так как другие слои ничего о нем не знают. Вся бизнес-логика инкапсулирована в domain слой в виде plain old java object, который не зависит вообще не от чего, а также предоставляет интерфейсы (репозиториев например) для инфраструктурного слоя и только в этом слое фактически и будет тот самый настоящий ООП, который все так упорно пытаются найти. Никакого стороннего кода в бизнес-логике нет, а соответственно весь сторонний код можно в любой момент поменять, не трогая бизнес-логику вообще.

    Для этого нужно открыть какую-нибудь книгу, где за руку проведут с нуля до конкретного приложения построенного с использованием этой архитектуры. Например Implementing domain-driven design, хоть эта книга и о DDD, но я уже говорил, что слоистая архитектура это де факто. С опытом, будет понятно, что в более простых приложениях количество слоев можно уменьшить, понимая на какой компромисс придется пойти, что иногда можно объединить domain и часть infrastructure и получить всем известный шаблон Active Record или вообще выбросить эти слои и получить шаблон transaction script, когда для решения просто не требуется что-то более сложное. Придет понимание, как можно начать с transaction script и в итоге постепенно катиться в сторону domain layer, через active record или не через active record если это когда-нибудь понадобится и тому подобное. Cтанет понятно, зачем, как и когда использовать патерны о которых написал Мартин Фаулер в своей книге Patterns of Enterprise Application Architecture.

    Полученные знания можно применить к любому языку. В том числе и PHP. Будет хорошо, если уровень этого сообщества хоть чуть-чуть будет подтягиваться к уровню Java, вместо того чтобы бомбить пятиуровневые ифы создавая такую цикломатическую сложность, что все метрики кода горят ярче красного.
    Ответ написан
    Комментировать
  • Не получается объявить двухмерный динамический массив?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Вы или тег "C++" уберите, или C++ используйте, а не C.
    using Map = std::vector<std::vector<char>>;
    Map map = {
       {1, 1, 1},
       {0, 1, 0},
       {0, 1, 0},
    };
    
    // ...
    void scaleMap(Map &map, int coefficient)
    {
       // ...
       Map newMap(newSize, std::vector<char>(newSize));
       // ...
       map.swap(newMap);
    }

    Всё просто, быстро и безопасно. Главное за границы массива не выходите.
    Ответ написан
    Комментировать
  • Как сервер находит запрашиваемый файл?

    @EvgeniiR
    https://github.com/EvgeniiR
    При запросе, например html файла, сервер или ОС ищет файл циклом

    Зачем, если есть путь?

    С массивами та же история? Например чтобы добраться до 11 элемента, просматриваются все предыдущие?

    В связном списке - да, перебором. В хэш-таблице обычно без перебора, т.е. за O(1) в среднем (если нет коллизий). Зависит от алгоритма.
    Ответ написан
    1 комментарий
  • Есть ли перспективы у программиста за Москвой И СПб?

    @dmfun
    Люди и по удаленке работают. Важны скилы. Junior будет немного получать по-любому.
    Конечно, в МСК и СПБ найти работу проще, но и в остальных городах вполне можно. Можно посмотреть проводят ли IT-конфы в городе, есть ли какая-то активность. В каждом городе по разному. Казань, Самара, Томск, Новосибирск, вполне платежеспособные города и движуха там есть.
    В более мелких городах посложнее, смотрить надо на айти-сообщество и какие есть предприятия. Где-то может и не быть, за все города ручаться не могу.

    Кстати, выгоднее разрабов держать на переферие, ибо дешевле. Но не в каждом опять же городе удастся создать офис и филиал. Думаю тут такой алгоритм. 1) найти городское сообщество в соц сетях. посмотреть кто где работает, кто сколько получает. 2) если сообщества как такового нет, конфы не проводятся, значит в городе тухляк. Если же наоборот, то надо пообщаться с людьми в комьюнити влиться, послушать, что эти люди думают. Но вполне может быть, что есть какая-то конторка, которая сидит и тихо пашет, в соседнем доме, выпускает игры для мобил с миллиоными оборотами :) Нужно все самому узнавать, вакансии думаю везде есть, но если самому не искать, не найдешь точно :)
    Ответ написан
    4 комментария
  • В чем отличие полиморфизма от реализации интерфейса?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Тут, на самом деле, необходимо чётко определить границы.

    Есть ООП как парадигма программирования. Одна из концепций ООП называется полиморфизм. Существуют различные реализации этой концепции в языках программирования.

    В C++ есть несколько реализаций полиморфизма. Вам, на данном этапе, скорее всего интересен только полиморфизм, основанный на подтипах. Это означает, что вызывающий код может работать с набором типов из определённой иерархии, без знания о том, какой это конкретно но тип: базовый или подтип.

    Касательно интерфейсов: в C++ их нет на уровне языка, как отдельной сущности. Однако же разница между интерфейсом и абстрактным классом никуда не делась.

    Пример "обычного полиморфизма":
    // Это "интерфейс", который представляет собой набор операций, которые можно произвести над объектом
    // В данном случае, по объекту можно постучать
    class IKnockable {
    public:
        virtual ~IKnockable() = 0;
    
        // Само по себе действие: "постучать"
        virtual void knock() const = 0;
    };
    
    // Реализация интерфейса классом Door
    class Door : public IKnockable {
    public:
        // ...
        void knock() const override { std::cout << "door" << std::endl; }
        // ...
    };
    
    // Реализация интерфейса классом Window
    class Window : public IKnockable {
    public:
        // ...
        void knock() const override { std::cout << "window" << std::endl; }
        // ...
    };
    
    // ...
    
    // Какая-то функция, которая может постучать  по каждому объекту из списка, 
    // не имея представления о том, что же это за объект
    void knock(const std::vector<std::shared_ptr<IKnockable>> &knockableObjects) {
        for (auto &&knockableObject : knockableObjects) {
            knockableObject->knock();
        }
    }
    
    // ...
    
    std::vector<std::shared_ptr<IKnockable>> v = {std::make_shared<Door>(), std::make_shared<Window>()};
    knock(v); // Сначала напечатает "door", потом напечатает "window"


    Ответ на ваш изначальный вопрос: это понятия из разных областей, одно из теории типов, другое из языков программирования. Интерфейс -- это одно из средств в языках программирования, для реализации определённого типа полиморфизма.
    Ответ написан
    3 комментария
  • Как сделать лицензионное соглашение и политику конфиденциальности?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Если приложение коммерческое, то это область в которой можно легко попасть в неприятности, поэтому я бы заплатил юристу за разработку этих документов. А если некоммерческое, то надо где-нибудь написать "Коммерческую деятельность не осуществляю, ничего не собираю, ни за что не отвечаю, приложение предоставляется как есть и используется вами на свой страх и риск".
    Ответ написан
    Комментировать
  • Нужно ли провинциальное высшее IT образование?

    CityCat4
    @CityCat4
    Внимание! Изменился адрес почты!
    Те, кто считает, что университет учит учиться, что он настраивает мозги на нужный лад — просто не пишите об этом здесь пожалуйста.

    Те, кто считает что это не так - идут во фриланс, до 30-ти сидят там и формошлепствуют, после 30-ти внезпано прозревают и начинают ныть, что их обманули и в ИТ вовсе нет легко достающихся сверхзарплат.

    На самом деле Вы хотите от нас не ответа на вопрос. На самом деле Вы решение уже приняли, и хотите от нас услышать подтверждение в его правильности. Ну так фиг Вам.

    Хотите уже сейчас идти формошлепствовать? You are welcome. Тысячи таких же, как Вы сидят на апворке зарабатывая на дошик. Хотите загнать себя в тупик - гоните. Быть может Вам удастся стать гением фриланса, к которому записываются за полгода. Если же нет - тут недавно вопрос был похожий - чувак в 30 лет спрашивал, как ему теперь дальше?
    Только не говорите, что 30 лет - это черт знает когда будет. Это будет гораздо скорее, чем вы думаете. И жизнь не кончится.

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

    Решение в любом случае за Вами.
    - С образованием Вас возьмут всюду, куда сможете пробиться
    - Без образования Ваш удел - фриланс и мелкие конторы, которые обычно кладут на наличие вышки.

    В ИТ нет легких и быстрых денег. Если Вы хотели этого - я Вас разочарую.
    Ответ написан
  • Правильны ли мои рассуждения в комментариях к коду?

    @majstar_Zubr
    C++, C#, gamedev
    У вас ошибка только в комментариях.
    Данное выражение new ничего не ищет, оно по сути пытается выделить память, сконструировать и инициализировать в этой памяти объект указанного типа. В данном случае будет выделено sizeof(int) байт. Причем выделение будет осуществлять void* operator new ( size_t count ), который после стандарта C++11 вообще может выкинуть std::bad_alloc exception, а конструирования и инициализации не произойдет, потому как int - фундаментальный целочисленный тип.

    Однако, современная практика написания кода на c++ подразумевает, что при использовании обычных указателей, каждое использование ключевого слова new сопровождается использованием ключевым словом delete в той же области видимости. Поэтому отсутствие delete aaa_num; считается ошибкой.
    Ответ написан
    2 комментария
  • Можно ли выбрасывать исключение в предикатах?

    inoise
    @inoise
    Solution Architect, AWS Certified, Serverless
    Держащий в руке молоток видит только гвозди


    Это про вас. Предикат обязан возвращать true/false. Эксепшены нужны для того чтобы отлавливать ошибки и передавать из вверх по стеку.

    Пример из жизни: на вопрос есть ли пирожки продавец или говорит да или разворачивается и уходит
    Ответ написан
    2 комментария
  • Как решить проблему фермеров и киллеров в реалистичных играх?

    @GreatRash
    Милиция должна защищать фермеров от киллеров иначе никак не забалансить (в рамках реализма). Ну или рэкет - часть киллеров защищает фермеров от других киллеров за мзду.
    Ответ написан
    Комментировать
  • Какие шаблоны проектирования js применяются на практике чаще всего?

    sfi0zy
    @sfi0zy Куратор тега JavaScript
    Creative frontend developer
    какие паттерны применяются чаще всего на практике и где

    Сразу отмечу, что все это чисто мое имхо, которое может не совпадать с мнением окружающих. В контексте фронтенда обычно все довольно просто. По моим наблюдениям в среднем сайте могут иметь смысл:
    1. Модули (делим код на независимые части)
    2. Фабрики (для компонентов интерфейса)
    3. Синглтоны (для хранилищ, точек сбора полифиллов / утилит и.т.д.)
    4. Адаптеры (для зависимостей и полифилов, которые могут измениться / выпилиться)
    5. Наблюдатели (для сбора происходящих событий в одном месте)
    6. Хранители (для сохранения действий пользователя и "Ctrl-Z")
    7. Стратегии (если действуем в зависимости от прилетевших данных)

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

    Важно понимать, что паттерны проектирования - это просто хорошие идеи по поводу того, как организовать большой объем кода в той или иной ситуации. Это не "изучи тайное знание, запомни, и делай так всегда", не "используй паттерны, потому что великие их используют", это скорее "если не уверен как организовать код, возьми готовую идею, она вроде работает". Если вы будете просто решать задачи, то через N лет практики вы сами их все "изобретете", только не будете знать, что у них есть названия. Эффективно будет организовать себе заметку о том, какие из этих идей для чего примерно применяют, а потом, в процессе работы, в нее подглядывать, если встал вопрос "как организовать этот код".
    Ответ написан
    7 комментариев
  • Как получить дробное число при делении 1 на 1?

    myjcom
    @myjcom Куратор тега C++
    Смотря что нужно.
    #include <iostream>
    #include <iomanip>
    #include <cstdlib>
    
    int main()
    {
      int a = 9;
      int b = 4;
      std::div_t result = div(a, b);
      std::cout << result.quot << " " << result.rem << std::endl;
      // Наверное это
      std::cout.precision(1);
      std::cout << std::fixed << static_cast<double>(a) / b << std::endl;
    }
    Ответ написан
    Комментировать
  • Как использовать вектор классов?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Ну только такие методы не должны классу user принадлежать. Было бы лучше создать новый класс, вроде Database, который используется для хранения пользователей. А уж у этого класса можно сделать методы вроде find или sort. Только сигнатура этих методов уже разумеется никаких векторов не содержит: вектор -- это деталь реализации в данном случае, которая может быть изменена потом.
    Ответ написан
    Комментировать
  • Что такое макросы в С++?

    myjcom
    @myjcom Куратор тега C++
    потому что x это 3 + 0; (целиком) это тупо текст, который будет вставлен вместо x;
    x * x == 3 + 0 * 3 + 0;

    получаем

    3 + (0 * 3) + 0;
    3 + 0 + 0;
    3;

    макросы в С++

    Атавизм
    иногда полезный
    https://en.cppreference.com/w/cpp/preprocessor/replace

    а так тут есть как минимум
    https://en.cppreference.com/w/cpp/language/constexpr
    https://en.cppreference.com/w/cpp/language/templates

    code
    #include <iostream>
    
    template<typename T>
    auto sqr = [](T x)
    {
      return x * x;
    };
    
    int main()
    {
      std::cout << sqr<int>(3 + 0);
    }


    что будет развернуто в что-то типа
    //...
    class __lambda_3_12
    {
      public: inline int operator()(int x) const
      {
        return x * x;
      }
    //...
    };
    //...

    Ответ написан
    Комментировать
  • Компиляция c++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    получается mainx узнает о том что есть функция printx() на этапе линковки [mainx.o] и [printx.o]?

    Да.

    Каким образом происходит передача информации в [mainx] что функция printx() существует?

    Это работа линковщика связывать ссылки на неопределённые символы с определениями этих символов.
    В main.o в месте вызова printx ставится команда вызова, в секции символов заводится неопределённый символ printx а в секции релокаций заводится запись, связывающая команду вызова с символом:

    objdump -dr mainx.o
    ...
    0000000000000000 <main>:
       0:   55                      push   %rbp
    ...
      3a:   89 c7                   mov    %eax,%edi
      3c:   e8 00 00 00 00          callq  41 <main+0x41>
                            3d: R_X86_64_PLT32      _Z6printxi-0x4
      41:   b8 00 00 00 00          mov    $0x0,%eax
      46:   c9                      leaveq 
      47:   c3                      retq   
    ...


    readelf -a mainx.o
    ...
    Relocation section '.rela.text' at offset 0x580 contains 12 entries:
      Offset          Info           Type           Sym. Value    Sym. Name + Addend
    ...
    00000000003d  001400000004 R_X86_64_PLT32    0000000000000000 _Z6printxi - 4
    ...
    
    Symbol table '.symtab' contains 25 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
    ...
        20: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _Z6printxi
    ...


    В printx.o в секции символов заводится символ, ассоциированный с адресом в коде, где определена функция printx:

    readelf -a printx.cpp
    ...
    Symbol table '.symtab' contains 24 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
    ...
        14: 0000000000000000    75 FUNC    GLOBAL DEFAULT    1 _Z6printxi
    ...

    Здесь value == 0 -- потому что printx оказалась по адресу 0 в секции .text.

    Линковщик объединяет входные секции согласно скрипту линковки, после чего вставляет конечные адреса символов в места, которые ссылаются на них.
    Ответ написан
    Комментировать
  • Есть ли для питона IDE на подобии как Delphi?

    longclaps
    @longclaps
    Такой IDE нет.

    ps Ваш вопрос мне очень понравился, и я дам на него развёрнутый ответ. Многолетней давности рыночный успех Delphi был обусловлен нехитрым трюком: кривая обучения "программиста" в её начальной фазе была очень пологой, и одолеть её мог любой кретин. Эта лёгкость обеспечивалась именно визуальным редактором форм.
    У низкого порога вхождения, разумеется, была своя цена. Рынок наводнили говнокодеры, не отягощённые общей програмистской культурой, а содаваемые ими продукты были безнадёжно одноразовы. Код-лапша, в котором бизнес-логика упихивалась в контролы, был неподдерживаем.
    С тех пор прошли эпохи, новые поколения говнокодеров освоили концепцию MVC (вместе с паттернами, хех), но говнокодеры старой закваски всё еще не вымерли. И когда я увидел ваш вопрос, я с ностальгией вспомнил старые времена.
    Сейчас на рынке рулят IDE, поощряющие создание поддерживаемого, документированного кода. Жалобы на необходимость прописывания вручную по пол страницы кода только для создания GUI главного окна вызывают лишь снисходительную усмешку: что с него возьмёшь, он - кодер старой школы. А по аватарке не скажешь )
    Ответ написан
    12 комментариев
  • А где можно программировать в двоичных и 16-ричных системах?

    ApeCoder
    @ApeCoder
    Изучаете ассемблер
    Изучаете машинные коды
    Пишете программу на ассемблере
    Вучную транслируете в машинные коды
    Записывате их в шестнадцатеричной системе счисления
    Любым редактором который это поддерживаете.
    Получаете работающую программу.

    Можно найти какой-нибудь эмулятор старого устройства чтобы почувствовать как ветераны писали код в 1986
    Ответ написан
    2 комментария
  • Как найти последовательные совпадения в массиве?

    NYMEZIDE
    @NYMEZIDE
    резюме - ivanfilatov.ru
    Реализуй конечный автомат. Подаешь последовательность.
    Читаешь, Запоминаешь первую цифру. Двигаешь автомат вправо.
    Если цифра та же самая - увеличиваешь счетчик +1. Проверяешь счетчик, не равен ли он 3м. Двигаешь автомат вправо.
    Если счетчик стал равен 3м - то двигаешься вправо до тех пор пока не получиться другая цифра.
    Если другая цифра - то проверяешь счетчик был равен или больше 3х.
    Если да - то двигаешь автомат влево ровно сколько раз, сколько равен счетчик и "красишь цифры". После двигаешь автомат вправо на сколько же позиций.

    Ну осталось только это дело реализовать на предпочитаемом ЯП.
    Ответ написан
    1 комментарий