• Написание blockchain менее чем за 200 строк кода на Go
    0
    Если появится принципиально новый вычислитель с мощностью более 51% всей мощности сети, и он не будет задействован в майнинге, то тогда блокчейну конец. Получится переподписать всю историю с самого начала и создать альтернативную историю. Но тут *скорее всего* сыграет роль огромное количество пользователей блокчейна, которые быстро используют тот же вычислитель в целях майнинга, и тогда такой проблемы не будет.

    С точки зрения того, чтобы взять и переделать первые блоки, а потом «приклеить» их к новым, это маловероятно, пока не обнаружена уязвимость в sha256, которая позволить делать прогнозируемые коллизии (но если она будет обнаружена сломается сразу весь механизм PoW, и блокчейну опять конец). Потому что если такая возможность будет, тогда можно будет и новые блоки модифицировать так, чтобы их не перемайнивать заново. Более того «векселя» в блокчейне имеют строго определенный формат, и вероятность того, что незначительное изменение в «векселе» позволит получить хеш-коллизию близка к нулю. Такую коллизию скорее более вероятно получить на целой цепочке ранних блоков, но получается, что нужно будет переподписать раннюю цепочку миллиарды раз, чтобы получить коллизию и «приклеиться» к новым блокам.
  • Написание blockchain менее чем за 200 строк кода на Go
    0
    По моему данный пример наглядно иллюстрирует тотальное непонимание системы блокчейн и того, зачем она нужна. В приведенном примере полностью отсутствует майнинг, который как раз гарантирует защиту децентрализованный данных при помощи PoW. Какой смысл хранить последовательные блоки, хранящие хеш предыдущего, если в такой системе можно обновить случайный блок в цепи, а потом за секунду перехешировать всю цепочку? Чем это вообще лучше обычной реляционной БД, которая уже готова, и которая предоставляет уровень «защиты от подтасовки» ровно такой же, то есть нулевой?
  • Просто добавь воды. Маленькая добавка H₂О повышает мощность ДВС и экономит топливо
    +2
    Достаточно известная примочка в кругах тюнеров. Позволяет получить дополнительные 10-20% мощности на сильно наддутом моторе. На атмосферниках смысла практически не имеет, дает слишком незначительный приход мощности и экономию на уровне погрешности измерений. Однако для турбомотора подача водяной пыли в цилиндры позволяет сдвинуть порог детонации, таким образом можно увеличить углы опережения зажигания и сделать более бедную смесь, что повышает КПД, снижает расход и повышает мощность. Также есть эффект повышения давления в цилиндре за счет испарения воды и появления пара. Насчет ржавения двигателя ничего сказать не могу, на моторах, которые я видел и разбирал ржавчины не было. Зато есть бонус для моторов с непосредственным впрыском, где топливо не проходит сквозь впускные клапана и не омывает их. Подача воды (или водометанольной смеси, что еще круче) отлично отмывает нагар с клапанов. Для распределенного впрыска, разумеется, такого бонуса нет, так как клапана и так омываются бензином.
  • Linux в кармане — на службе у фотографа
    0
    А в чем фишка снимать в RAW, а потом дергать оттуда превью джипег?
  • Пишем maintainable код
    0
    А в чем проблема исправить кусок написанного кода а не реализацию интерфейса, ну допустим там не использовать другого наследника, а просто изменить реализацию? В этом абсолютно нет никакой разницы, однако тут интерфейсы преподносятся как великое благо. Интерфейсы не дают большей гибкости, чем конкретная реализация, это я и хочу сказать. Это инструмент для проектирование иерархии классов в подходящих для этого задачах.
  • Пишем maintainable код
    0
    Не уверен, что такое возможно. Вот например в вашем примере, интерфейс — это копия конкретной реализации. И как можно первично все предусмотреть, ведь делая интерфейс все обычно опираются на то, что уже будет под ним. Это как сказать, что можно например спроектировать отличный интерфейс для _любой_ базы данных, изначально разрабатывая его под какую-то конкретную одну…
  • Пишем maintainable код
    0
    Если команда хорошо знает код, который пишет, то обычно быстро все становится понятно. А если команда большая, и никто уже ничего не знает, то да, юнит-тесты — единственный выход.
  • Пишем maintainable код
    0
    Например можно использовать интеграционные тесты :)
    Кстати расскажите, а как можно использовать юнит-тесты для проверки корректности интеграции двух систем?
  • Пишем maintainable код
    0
    Тут есть еще такой аспект. Чаще всего, как я уже и говорил, интерфейсы делаются не первично, а как прокси для уже некоторой существующей реализации, поэтому говорить о полноценной абстрактности достаточно сложно. Единственное, что чего они отлично подходят, так это для юнит тестов, но это уже совсем другая история.

    Получается, что на самом деле в случае интерфейсов у нас есть такой же неуниверсальный код, как и «конкрит» реализация, только в одном случае для внесения правок нам надо написать новый класс наследник от интерфейса и кинуть его в контейнер, а в другом стереть код в конкрит реализации и написать новый. Разницы по-моему вообще никакой, только в первом случае у нас есть код интерфейса + код класса, в во втором просто код класса. Если я не прав, прошу пояснить.

    А если вдруг потребовалось нечто, что требует изменения интерфейса, какая разница, тащить через весь код обновленный интерфейс, или конктрит реализацию?
  • Пишем maintainable код
    0
    Получается, что вместо одного программиста, Вам будет нужно десять. Все еще хотите код покрытый тестами?

    А вы не думали, что такая гадостная вещь, как регрессия, в основном происходит не потому что в команде одни осьминоги с кривыми щупальцами, а потому что в проекте там много кода, что нужна большая команда, а в большой команде никто уже целиком картину не видит и может запросто написать код, который сломает старый? Получается, что юнит-тесты это отличный механизм борьбы с регрессией, но применение этого подхода косвенно регрессию провоцирует…
  • Пишем maintainable код
    0
    И вообще скажите честно, Вам машина нужна чтобы на ней ездить или детали менять?
  • Пишем maintainable код
    0
    Вы не поверите, но в современных машинах обычно можно поменять только крупные узлы. Например поменять шестеренку в коробке передач или флап во впускном коллекторе невозможно, нужно покупать только новый узел или колхозить. А вот на старых тазиках можно поменять и купить ЛЮБОЙ болтик, вообще все что угодно, но что-то тазики не очень популярны. Зато машина становится легче, проще, дешевле. И да, такие машины покупают.
  • Пишем maintainable код
    0
    Жизнь вообще сложная штука. Но хорошей практикой является делать то, что от тебя требуется, а не то, что считаешь «правильным». Если заказчик хочет получить учет автомобилей, но стоит делать программу с учетом тяжелой строительной техники и детских колясок. Это просто усложнит код, повысит затраты на разработку и увеличит штат сотрудников. И Вы же не ожидаете, заказав в макдоналдсе гамбургер подождать лишний час, что вам сделали такой бургер, который при желании может стать и блинчиком?

    Тут возникают следующие нюансы, во первый в какой-то момент кода станет так много, что например понадобится больше разработчиков. Только вот увеличение штата не приводит к линейному росту производительности, а порой существенно ее снижает. Для того, чтобы грамотно организовать процесс разработки в большой команде, нужен поистине одаренный руководитель, ведь руководство большой командой это искусство, которое порой в разы сложнее и так непростого программирования. Вашей команде возможно очень повезло, если у Вас есть такой замечательный лидер. Но даже с отличным руководителем затраты на кросс-функциональное взаимодействие могут составить бОльшую часть времени работы команды, а это неэффективно. Также в большой команде начинаются бои за лидерство и перетягивание одеяла. Это неизбежно, а это наносит существенный урон качеству продукта в целом.

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

    Однако для того, чтобы иметь возможность использовать микрокоманды необходимо ограничивать себя в размерах кода, так как 1-2 человека просто не смогут адекватно поддерживать сотни тысяч строк кода и тесты к ним. С одной стороны нет документации (о ее необходимости я бы конечно поспорил, я сторонник простого и самодокументируемого кода), нет тестов, нет витьеватых суперрасширяемых конструкций, но с другой стороны, небольшой объем кода позволяет в нем намного лучше разбираться и значительно сократить количество регрессий, а также повысить скорость и эффективность работы.

  • Пишем maintainable код
    0
    Не угадали, я несколько лет работаю в достаточно крупной софтверной компании, разрабатывающей серьезные банковские продукты. Участвую в нескольких проектах и наблюдаю за многими другими, так как приходится с ними интегрироваться и проводить консультации.

    Из того что я вижу, я и делаю выводы. Команды, которые делают продукт, который работает, обычно достаточно спокойно относятся к качеству кода, и предпочитают функционал качеству кода. Другие же команды, которые могут сидеть год, а потом оказалось, что они за все время написали только юнит-тесты, обычно даже до первого релиза не доходят, так как просто не успевают в сроки, и иногда проекты сворачивают, как неуспешные.
  • Пишем maintainable код
    +1
    В этом случае иерархия классов как раз уместна.
    Но например стоит ли, проектируя автопарк, делать не IVehicle, а например IAsset, который в свою очередь расширяет ISomething, который расширяет IUniverse? А также сделать так, что машины могут быть как с обычными двигателями, так и потенциально с ядерными (разумеется с интерфейсом обычного)?
  • Пишем maintainable код
    –4
    Задача грамотного программиста — удержать свой проект в «масштабах 100 строчек». Вы будете удивлены, какие сложные приложения могут быть написаны малым количеством кода. Также как и простейшее приложение из пары табличек может занимать сотни тысяч строк сомнительного кода.
    Понятное дело, что каждая задача требует решения, которое порождает лишние строчки, но зачем целенаправленно раздувать свой код лишними конструкциями, для меня до сих пор остается большой загадкой.

    Даже если проект правда огромен, наиболее разумным решением будет разбить его на много «конкрит» кирпичиков из по вашему мнению «неподдерживаемого» кода, и красивое и в то же время простое ядро, в которое изменения вносятся крайне редко и при большой необходимости. Весь остальной мусор живет в одноразовых кирпичиках. Именно такие проекты имеют шанс разрабатываться быстро, могут пережить большую команду и хреновых специалистов.
  • Пишем maintainable код
    –3
    1) это же очевидно, что нет более постоянно решения, чем временное. Даже если начать переписывать, опять же очень не факт что новый проект вообще завершится, а не утонет в утехах тру программистов
    2) в хорошей системе все делается лучше, только вот не факт, что паттерны и модные фишки облегчат жизнь, а не загонять разрабов в полный рефакторинг
    3) я имел в виду задержки в разработке, не в коде. От кода обычно проблем меньше, чем от человеческого фактора
  • Пишем maintainable код
    0
    Ну хорошо, у нас было 10 строчек кода, стало 100. Из новых 100 строк около 20 менять точно не надо будет.
    В первом решении не надо будет менять 0 строчек, а во втором 20.
    По моему достойный результат :)
  • Пишем maintainable код
    –2
    К сожалению многие программисты забывают, зачем они делают свою работу. Стремятся написать «идеальный код», но не думают о том, какие задачи они решают и для чего.

    Рассмотрим несколько примеров:
    1) команда делает некоторый продукт, который при правильном позиционировании может стать индустриальным стандартом. Однако не только эта компания занимается этим, и то, насколько быстро продукт будет выведен на рынок, будет играть решающую роль в его дальнейшем развитии
    2) команда разработки и поддержки некой системы документооборота внезапно получает новые правила для набора документов, регламентируемый государством. Например система учета зарплаты. Если до конца месяца система не будет внедрена и по ней не будет произведен новый расчет зарплат и выписок, то в лучшем случае компания попадает на огромные штрафы, или на штрафы попадают ее клиенты
    3) в банковской сфере задержка даже в день может нести колоссальные убытки

    И что, в каком нибудь из этих случаев ответ тимлида о том, что не успеем, мол еще не все юнит тесты написаны и не все иоки бахнуты будет адекватен?

    Так что скорее те проекты, где есть много времени — как раз они тепличные
  • Пишем maintainable код
    –3
    Потому что если продукт пишется под девизом «у нас достаточно времени, чтобы сделать хорошо», то обычно он уходит в пучину треша и угара
  • Пишем maintainable код
    0
    А потом люди начитаются что так стоит делать, и как раз так и лепят. Я видел очень много кода, где паттерны применены в простых местах и вообще нужны, а там где правда надо было подумать, разработчика уже не хватило, и там совсем странные дела происходят. Вообще кода, в котором паттерны применены адекватно задаче весьма мало, обычно их везде лепят, потому что это «круто» и «технологично».
  • Пишем maintainable код
    +2
    Инфраструктура кода, которая обспечивает «красивую» поддержку кода обычно может занимать места больше чем сам эффективный код, а ведь ее тоже надо поддерживать. Применение современных модных паттернов порой приводит к несоразмерному раздуванию кода, а значит к повышению вероятности ошибок. Также больший объем кода требует больше тестирования, а если это юнит-тестирование, то дополнительного времени разработчиков. При том что юнит тесты ничего не гарантируют.

    И возникает вопрос, что лучше: 100 строк простого кода без тестов или 1000 строк кода покрытого тестами. У меня нет однозначного ответа на этот вопрос, но лично мне приятнее первый вариант.

    Также не стоит забывать о вопросах производительности, конечно это не всегда самое важное, но современные тенденции запуска хелоуворлда на кластерах несколько удивляют.
  • Пишем maintainable код
    +2
    И поясню свое мнение, почему я так считаю.
    Создание интерфейса избыточно, так код изначально проектируется под SMTP. То есть по факту добавляя интерфейс, мы не даем сильно больше возможностей для расширения (мы вообще тупо копируем интерфейс SMTP), но идеологически уже привязываемся к интерфейсу. Далее этот интерфейс пойдет дальше в код, и может возникнуть ситуация, когда появится какой то принципиально новый мессенджер, ну вот допустим телеграм, и мы захотим писать в него, а не в почту. Получится, что придется делать рефакторинг (а это бесполезная с точки зрения бизнеса работа) или отказаться от нового решения. С куском «говнокода» проще, его просто удалил и поставил что-то новое. Далее IoC и контейнеры это уже следствие неуместного применения интерфейсов.

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

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

    Предлагаемый Вами подход может иметь смысл, если рядом сидит человек, знающий будущее, который скажет что сразу предусмотреть в интерфейсе. Но я вот таких не видел…
  • Пишем maintainable код
    0
    По моему мнению код в самом начале статьи наиболее адекватен для решения поставленной задачи.
    Введение интерфейсов, IoC и депенденси контейнера избыточны для конкретного случая
  • Пишем maintainable код
    –3
    А юнит тест сможет ответить лишь на вопрос, сможет ли полностью изолированный класс дернуть команду мока почтового сервиса. На вопросы почему было дернуто слишком много и мало раз в боевом окружении он вряд ли ответит.
  • Пишем maintainable код
    –4
    И такой подход с пиханием паттернов куда не попадя приводит к тому что приложение разрабатывается слишком долго, работает так-же. Но конечно у таких приложений бывают и преимущества, ведь хелло ворлд почти не тормозит, и ему хватит всего 86гб памяти.
  • Пишем maintainable код
    –3
    А чем неуместное использование паттернов это не решение в лоб? Единственное что мне приходит на ум почему оно не в лоб, это потому что оно через ***у :)
  • Пишем maintainable код
    0
    А серьезный проект это какой? Когда пишется сложный продукт в сжатые сроки с реализацией всех бизнес потребностей и который в итоге работает как этого хочет клиент, или долгий проект у аутсорсера на несколько лет, где можно с умным видом ковырять в носу, переносить сроки и ленивенько писать юниттесты?
  • Пишем maintainable код
    –2
    Клевая идея, совершенно честно. У нее есть только одна проблема: время, необходимое на то, чтобы проверить, что обработка заказа рассылает все 18 нужных писем в разных сценариях. Даже если это автоматизировать (включая работу с почтовым ящиком), все равно будет небыстро. А юнит-тест проверяет это за секунды, и каждый раз, при каждом билде.


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

    Так мы получим нужное решение, которое кроме всего прочего декомпозировано (сервер приложений и демон), транзакционно (если приложение упадет, то почта не будет отмечена как отправленная и не потеряется) и простое (несколько модулей, которые может написать и поддерживать даже школьник).
  • Пишем maintainable код
    –4
    Я не говорю, что код надо писать одной функцией на миллион строк. Или что паттерны это зло, их вообще использовать не стоит. Но придумывать синтетические ситуации для того, чтобы использовать паттерн, потому что это круто — вещь очень сомнительная. Стоит понимать, для чего пишется проект, какие у него, нужен ли он заказчику, или это «русский бизнес».

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

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

    Насчет мира PHP, достаточно сложно говорить на его примере вообще о чем либо. Это достаточно неплохой язык, на котором можно при желании делать красивые, качественные и отличные решения. Но изначально этот язык проектировался как перл для домохозяек, и обладает крайне низким порогом для вхождения, что делает с одной стороны его простым и легким в изучении, а с другой стороны притягивает к себе начинающих программистов, не обладающих достаточным опытом и практикой для того, чтобы оценить адекватность и применимость подхода и решения. Поэтому они начинают бездумно использовать то, что сейчас модно и наиболее афишируется, то есть всякие иоки, юнит тесты и контейнеры, и в итоге не понимают, что делают не совсем то. Но опыта для sanity check своего решения у них пока еще нет, он будет позже
  • Пишем maintainable код
    –12
    Запустить и проверить? Или Вы искренне считаете, что если сервис будет работать на моке, то он 100% заработает в реальном боевом окружении? Попробуйте мыслить чуть дальше, чем своим кодом. Не только программой, но еще и всем стеком, а также прилегающей инфраструктурой. И окажется, что написать такой юнит-тест, который все учтет, может оказаться очень проблематичным. А также это может вселить ложную уверенность в том, что раз код протестирован, то он работает. А на самом деле юнит тест будет проверять ту логику, которая предполагалсь. А то что программист упустил в своем коде, он упустит и в тесте, так как просто не думал об этом
  • Пишем maintainable код
    –8
    Отличный пример, как из простого куска кода, который пишется за несколько минут, сделать огромную структуру, увеличить количество кода в разы, и тем самым снизить его надежность, поддерживаемость и простоту, а также повысить косты на разработку ПО.

    Наглухо завязались на SMTP? Ужас то какой. А что, сейчас используется еще что-то? Что, в будущем появится еще какой-то протокол? У него будет точно такой же интерфейс? Уверены? Точно, точно не придется переделывать все приложение, потому что интерфейс мейлера просто не был предусмотрен для чего-то совсем нового?
    Или может быть источник данных из БД вдруг надо будет заменить на лоулевел драйвер флоппика? Серьезно?

    Все, что тут описано, это борьба очень средненького программиста с самим собой и получение им удовольствия от того, что он использовал паттерн, хоть и не к месту, сделал интерфейс, а интерфейсы повышают ЧСВ, это факт, ну и бахнул ИОК по приколу.

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

  • Робот-помощник Лекси взял первое место на Imagine Cup
    0
    Так намного интереснее, я бы поставил этот ролик вообще первым делом.

    На видео приведены примеры, как Лекси отвечает на сильно контекстно-зависимые вопросы: «какая у меня сегодня норма» и т.п. Как он понимает, в каком контексте нужно отвечать? Он правда *настолько* умный, что понимает, что с ним происходит, и что творится вокруг, как например, что девушка положила в еду один ингридиент, и следует положить следующий, или это все таки на видео показан небольшой «маркетинг»?
  • Робот-помощник Лекси взял первое место на Imagine Cup
    +5
    Рассказали бы немного в посте о том, что это вообще за проект и что он делает…
    А то в посте есть только унылый получасовой видос о том, как оно устроено, и описание печенек на выставке. А по самому проекту вообще не понятно что это. Очень хотелось бы увидеть короткий «рекламный» видос о том, что же это все таки за робот
  • Роботы в медицине
    +5
    Очень уже робот RIBA напоминает мне одного персонажа…
  • Таможенным пошлинам на посылки все-таки быть, причем скоро
    0
    А с aliexpress можно через Вас заказывать?
  • Разработка коммерческого электронного устройства с нуля
    0
    А купить уже можно?
  • Выделенные серверы под водой, буквально!? Перспективы разведения рыб в серверах?!
    +1
    А зачем нужно выравнивать давление в харде, кроме как для того, чтобы крышку не вспучило?
  • Выделенные серверы под водой, буквально!? Перспективы разведения рыб в серверах?!
    –6
    Интересно, а почему жесткий диск не сможет работать в масле? Насколько я знаю камера с вращающимися блинами и головкой полностью герметична
  • Цифровой код китайских доменов
    +1
    Напомнило lurkmore.to/265