<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Денис Королёв</title><generator>teletype.in</generator><description><![CDATA[Денис Королёв]]></description><image><url>https://img1.teletype.in/files/4c/07/4c0763e7-1217-43e9-becc-3a88d66d0d82.png</url><title>Денис Королёв</title><link>https://leprosus.ru/</link></image><link>https://leprosus.ru/?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/leprosus?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/leprosus?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Tue, 05 May 2026 10:46:51 GMT</pubDate><lastBuildDate>Tue, 05 May 2026 10:46:51 GMT</lastBuildDate><item><guid isPermaLink="true">https://leprosus.ru/feasibility-study-methodology</guid><link>https://leprosus.ru/feasibility-study-methodology?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus</link><comments>https://leprosus.ru/feasibility-study-methodology?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus#comments</comments><dc:creator>leprosus</dc:creator><title>Технико-экономическое обоснование (ТЭО) в жизни инженера</title><pubDate>Sat, 05 Jul 2025 20:46:21 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/f4/c9/f4c9b00e-c593-46c2-b724-cfe23a00d3d8.png"></media:content><category>Методологии</category><description><![CDATA[<img src="https://img1.teletype.in/files/c0/9b/c09b9848-782e-4147-ad18-2071ad4c2568.jpeg"></img>Данную статью я бы начал с простого ответа на вопрос читателя: &quot;на кой мне про это знать?&quot;]]></description><content:encoded><![CDATA[
  <p id="wsKb">Данную статью я бы начал с простого ответа на вопрос читателя: &quot;на кой мне про это знать?&quot;</p>
  <p id="qiQw">Любой инженер во время работы сталкивается с ситуацией, требующей от него принять решение в пользу той или иной технологии, методики, способа.</p>
  <figure id="CdTy" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/c0/9b/c09b9848-782e-4147-ad18-2071ad4c2568.jpeg" width="1280" />
    <figcaption>Let&#x27;s help crypto housekeeper Kuza make the right choice.</figcaption>
  </figure>
  <p id="nbqL">Современный инженер, я сужу исходя из собственной насмотренности, использует интуицию в качестве одного из сильнейших своих &quot;профессиональных навыков&quot;.</p>
  <p id="Hu1t">В статье речь пойдёт именно про подход как осознанно и объективно принять выбор.</p>
  <h2 id="zT4t">Задача</h2>
  <p id="qv9f">В качестве задачи предлагаю сделать выбор быстрого алгоритма шифрования для обеспечения целостности данных за счёт цифровой подписи с минимальной утилизацией ресурсов для языка программирования <a href="https://go.dev/" target="_blank">golang</a></p>
  <h2 id="mRwV">Возможные варианты</h2>
  <p id="SEDg">На рынке существует несколько решений, от всем известных, до государством одобряемых.</p>
  <p id="1cK5">Перечислим их:</p>
  <ul id="pZpd">
    <li id="EvWi"><a href="https://pkg.go.dev/crypto/rsa" target="_blank">RSA</a></li>
    <li id="dYq1"><a href="https://pkg.go.dev/crypto/ed25519" target="_blank">Ed25519</a></li>
    <li id="WmlP"><a href="https://github.com/ddulesov/gogost" target="_blank">ГОСТ Р 34.10</a></li>
  </ul>
  <h2 id="sqID">Критерии оценки</h2>
  <p id="7OpR">Методика называется технико-экономическое обоснование не спроста.</p>
  <p id="MHDw">Это означает, что нужно придумать список технических и экономических критериев для оценки.</p>
  <h3 id="y5jH">Технические критерии</h3>
  <pre id="sGn6" data-lang="markdown">| Наименование         | Вес | Обоснование веса                                                            |
|----------------------|-----|-----------------------------------------------------------------------------|
| Утилизация CPU       | 3   | Самая дорогая стоимость масштабирования                                     |
| Утилизация RAM       | 2   | Средняя стоимость масштабирования                                           |
| Наличие зависимостей | 2   | Чем больше зависимостей, тем выше вероятность внешнего дефекта и уязвимости |</pre>
  <p id="QjV2"><strong>Почему вес утилизации CPU - 3?</strong></p>
  <p id="sxss">Это обусловлено стоимостью увеличения производительности CPU, на текущий момент она самая высокая.</p>
  <p id="zICy"><strong>Почему вес утилизации RAM - 2?</strong></p>
  <p id="p6qy">Стоимость расширения же RAM уступает по цене улучшению CPU; масштабирование всё ещё не бесплатно.</p>
  <p id="eEqs"><strong>Почему наличие зависимостей - плохо?</strong></p>
  <p id="3m7H">Говоря языком математики (теорией вероятностей), то любое стороннее решение - это некая вероятность дефекта <em><u>P(defect)</u></em>, допущенного сторонним разработчиком, плюс вероятность уязвимости <u><em>P(vulnerability)</em></u>.</p>
  <p id="fzkD">Грубо говоря, каждая прямая зависимость обладает вероятностью, что вам, как инженеру, принявшему решение использовать ту или иную зависимость, придётся нести ответственность за внешнего разработчика:</p>
  <pre id="t6Dp" data-lang="latex">P(dependency) = P(defect) + P(vulnerability)</pre>
  <p id="vQSV">Если зависимостей несколько, то вероятностью является сумма каждой зависимости:</p>
  <pre id="XopB" data-lang="latex">P(dependency) = P(dependency 1) + P(dependency 2) + ... + P(dependency N)</pre>
  <p id="S0Df">Как оценить эти вероятности - это отдельная большая статья (пишите в комментарии, интересно ли будет про такое читать).</p>
  <h3 id="HpFm">Экономические критерии</h3>
  <pre id="1StE" data-lang="markdown">| Наименование            | Вес | Обоснование веса                          |
|-------------------------|-----|-------------------------------------------|
| Стоимость владения      | 2   | Для сокрашения статических затрат         |
| Стоимость сопровождения | 3   | Для сокрашения динамических затрат        |
| Стоимость внедрения     | 1   | Каждое решение обладает разной сложностью |</pre>
  <p id="5QOM"><strong>Почему вес стоимости владения - 2?</strong></p>
  <p id="ISuQ">Сперва определим, что это такое: это та стоимость, которую нужно выплатить за использование. В нашем списке речь идёт про открытые алгоритмы шифрования, стоимость которых пока равна нулю.</p>
  <p id="5XMz">Отвечая на вопрос, если даже стоимость владения была бы выше нуля, то для любой коммерческой компании эта затрата была бы разовой (для пожизненной лицензии) или ежегодной (для подписной модели).</p>
  <p id="bS53"><strong>Почему вес стоимости сопровождения - 3?</strong></p>
  <p id="TOaQ">Стоимость зарплат инженеров по эксплуатации и разработке чаще всего заметно выше лицензионных сборов, поэтому вес выше предыдущего.</p>
  <p id="9jr3"><strong>Почему вес стоимости внедрения - 1?</strong></p>
  <p id="wVcR">Разработка ПО для компании на базе любого из перечисленных решений будет стоить какого-то количества человеко-часов, которые никогда не бывают бесплатными.</p>
  <h2 id="aEZR">Эксперимент</h2>
  <h3 id="ODEN">Что будет выполнять</h3>
  <p id="65wP">Алгоритм должен взять тестовый набор данных, сгенерировать для него подпись и её проверить для указанных данных.</p>
  <h3 id="CRvp">Детали</h3>
  <p id="oZwp">Для проведения эксперимента будут использоваться базовые инструменты языка программирования. </p>
  <p id="gBfI">Также будут добавлены следующие флаги для запуска тестов:</p>
  <ul id="3oIn">
    <li id="ByZ2">test.benchmem - для отображения утилизации RAM</li>
    <li id="ia9G">test.benchtime=5s - для увеличения эксперимента с 1 секунды до 5</li>
  </ul>
  <p id="tFu7">Эксперимент будет проводиться на железе:</p>
  <ul id="jC3q">
    <li id="rfxm">ОС - MacOS</li>
    <li id="MgyC">CPU - Apple M3 Max (ARM64)</li>
    <li id="HMpF">RAM - 48 Gb</li>
  </ul>
  <h3 id="W026">Benchmark для RSA с 2048 битным ключём</h3>
  <p id="DhoQ"><strong>Почему 2048 битный ключ?</strong></p>
  <p id="cwGx">Алгоритм шифрования RSA достаточно старый, обладает определённым набором криптографических слабостей. Для того, чтобы его справедливо уравнять с остальными, ключ шифрования необходимо увеличить. Чтобы сравнение было хоть сколько-то адекватно, увеличивать ключ до бесконечности мы не можем. На текущий момент двухкилобитный ключ вполне достаточен.</p>
  <blockquote id="EtSQ">Конечно, для принятия более взвешенного решения, нужно бы отдельно провести анализ размера ключа, для обеспечения более объективного выбора. Я отказался от этого в пользу сохранения читаемости текста.</blockquote>
  <pre id="HehN" data-lang="go">package test

import (
	&quot;crypto&quot;
	&quot;crypto/rand&quot;
	&quot;crypto/rsa&quot;
	&quot;log&quot;
	&quot;testing&quot;
)

var msg = []byte(&quot;Let&#x27;s help crypto housekeeper Kuza make the right choice&quot;)

func BenchmarkRSA2048(b *testing.B) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		log.Fatal(err)
	}

	pub := &amp;priv.PublicKey

	var sign []byte

	b.ResetTimer()
	for i := 0; i &lt; b.N; i++ {
		sign, err = rsa.SignPKCS1v15(rand.Reader, priv, crypto.Hash(0), msg)
		if err != nil {
			log.Fatal(err)
		}

		err = rsa.VerifyPKCS1v15(pub, crypto.Hash(0), msg, sign)
		if err != nil {
			log.Fatal(err)
		}
	}
}</pre>
  <p id="YM8I">Что важно отметить:</p>
  <ul id="J80g">
    <li id="7MFR">код максимально простой</li>
    <li id="RF7v">данный алгоритм входит в базовые зависимости языка программирования</li>
    <li id="XXrX">данные не хешируются для создания подписи и её верификации</li>
  </ul>
  <p id="z2sT">Результат:</p>
  <pre id="j4pn" data-lang="shell">goos: darwin
goarch: arm64
cpu: Apple M3 Max
BenchmarkRSA2048-10    1,308    923,656 ns/op</pre>
  <h3 id="ID32">Benchmark для Ed25519</h3>
  <pre id="WExq" data-lang="go">package test

import (
	&quot;crypto&quot;
	&quot;crypto/ed25519&quot;
	&quot;log&quot;
	&quot;testing&quot;
)

var msg = []byte(&quot;Let&#x27;s help crypto housekeeper Kuza make the right choice&quot;)

func BenchmarkEd25519(b *testing.B) {
	pub, priv, err := ed25519.GenerateKey(nil)
	if err != nil {
		log.Fatal(err)
	}

	var sign []byte

	b.ResetTimer()
	for i := 0; i &lt; b.N; i++ {
		sign, err = priv.Sign(nil, msg, &amp;ed25519.Options{})
		if err != nil {
			log.Fatal(err)
		}

		err = ed25519.VerifyWithOptions(pub, msg, sign, &amp;ed25519.Options{})
		if err != nil {
			log.Fatal(err)
		}
	}
}
</pre>
  <p id="BQeB">Что важно отметить:</p>
  <ul id="AvNS">
    <li id="6Dp2">код максимально простой</li>
    <li id="sNDf">данный алгоритм входит в базовые зависимости языка программирования</li>
    <li id="47iy">данные не хешируются для создания подписи и её верификации</li>
  </ul>
  <p id="ieJv">Результат:</p>
  <pre id="L18j" data-lang="shell">goos: darwin
goarch: arm64
cpu: Apple M3 Max
BenchmarkEd25519-10    15,927    73,565 ns/op</pre>
  <h3 id="7bfb">Benchmark для ГОСТ Р 34.10</h3>
  <pre id="tabw" data-lang="go">package test

import (
	&quot;crypto&quot;
	&quot;crypto/rand&quot;
	&quot;log&quot;
	&quot;testing&quot;

	&quot;github.com/ddulesov/gogost/gost3410&quot;
)

var msg = []byte(&quot;Let&#x27;s help crypto housekeeper Kuza make the right choice&quot;)

func BenchmarkGOST3410(b *testing.B) {
	curve := gost3410.CurveIdtc26gost341012512paramSetA()

	priv, err := gost3410.GenPrivateKey(curve, gost3410.Mode2012, rand.Reader)
	if err != nil {
		b.Fatal(err)
	}

	var pub *gost3410.PublicKey

	pub, err = priv.PublicKey()
	if err != nil {
		b.Fatal(err)
	}

	var sign []byte

	b.ResetTimer()
	for i := 0; i &lt; b.N; i++ {
		sign, err = priv.SignDigest(msg, rand.Reader)
		if err != nil {
			b.Fatal(err)
		}

		_, err = pub.VerifyDigest(msg, sign)
		if err != nil {
			b.Fatal(err)
		}
	}
}</pre>
  <p id="fmKt">Что важно отметить:</p>
  <ul id="RTvv">
    <li id="nPsg">в государственных структурах до сих пор не научились давать адекватные названия</li>
    <li id="wEtk">сигнатура зависимости местами далека от интуитивно понятной</li>
    <li id="D2zh">данный алгоритм является внешним, поставляется отдельной зависимостью</li>
    <li id="5MeU">данные не хешируются для создания подписи и её верификации</li>
  </ul>
  <p id="iH6w">Результат:</p>
  <pre id="oWds" data-lang="shell">goos: darwin
goarch: arm64
cpu: Apple M3 Max
BenchmarkGOST3410-10    80    12,692,735 ns/op</pre>
  <h3 id="4466">Сводная таблица результатов</h3>
  <pre id="8XTh">| Эксперимент | Время | Итераций | Время одной операции | Утилизация RAM | Аллокаций RAM |
|-------------|-------|----------|----------------------|----------------|---------------|
| RSA2048     | 5 s   | 6415     | 900,552 ns           | 1,888          | 11            |
| Ed25519     | 5 s   | 81256    | 74,015 ns            | 88             | 2             |
| GOST3410    | 5 s   | 471      | 12,407,072 ns        | 3,981,786      | 48,399        |</pre>
  <p id="H3do">Пояснения:</p>
  <ul id="Hmbb">
    <li id="alOo">Время - это период прохождения эксперимент</li>
    <li id="epQQ">Итераций - число успешных операций подписи и её проверки</li>
    <li id="6uCf">Время одной операции - это необходимый период, требуемый железу на выполнение одного цикла генерации подписи и её проверки</li>
    <li id="gIVt">Утилизация RAM - сколько байт памяти будет выделено для выполнения одного цикла</li>
    <li id="V9rX">Аллокаций RAM - сколько выделений памяти будет сделано для выполнения одного цикла</li>
  </ul>
  <h3 id="ISIQ">Интерпретация результатов</h3>
  <pre id="WITu">| Оценка                             | Вес | RSA2048 | Ed25519 | GOST3410 |
|------------------------------------|-----|---------|---------|----------|
| Утилизация CPU                     | 3   | M       | S       | L        |
| Утилизация RAM                     | 2   | M       | S       | L        |
| Наличие зависимостей у решения     | 2   | -       | -       | +        |
| Стоимость владения технологией     | 2   | 0       | 0       | 0        |
| Стоимость сопровождения технологии | 3   | S       | S       | S        |
| Стоимость внедрения                | 1   | S       | S       | S        |</pre>
  <p id="ekG8">Легенда:</p>
  <ul id="a2Qc">
    <li id="Bvri"><strong>L</strong> - высокая (значение - 3)</li>
    <li id="Dqji"><strong>M</strong> - средняя (значение - 2)</li>
    <li id="znPY"><strong>S</strong> - низкая (значение - 1)</li>
  </ul>
  <p id="VLtQ">Пояснения:</p>
  <ul id="3uCd">
    <li id="SMPb">Самая высокая утилизация CPU у ГОСТ Р 34.10, времени на одну операцию требуется разительно больше, чем остальным; на втором месте идёт RSA; лидером является - Ed25519</li>
    <li id="tOUW">Самая высокая утилизация RAM и высокое число аллокаций также у ГОСТ Р 34.10; на втором месте - RSA; лидером является - Ed25519</li>
    <li id="zKGI">ГОСТ Р 34.10 выполнено отдельной зависимостью, остальные решения поддерживаются языком программирования</li>
    <li id="OFoi">Для использования всех трёх алгоритмов не потребуется никаких выплат - все они поставляются под свободными лицензиями</li>
    <li id="k8kw">Как показали примеры кода выше, реализация нужного алгоритма на базе каждого из решений не потребует больших интеллектуальных вложений, следовательно, стоимости сопровождения и внедрения будут низкими</li>
  </ul>
  <h3 id="x9ou">Расчёты</h3>
  <p id="1yuN">Для того, чтобы мы могли сравнить алгоритмы, нужно написать формулу для расчёта оценок.</p>
  <p id="QHqf">Предлагаю использовать вот такую достаточно простую для понимания формулу:</p>
  <pre id="GTw1" data-lang="latex">score = сpu_util * cpu_util_weight 
      + ram_util * ram_util_weight
      + is_dep * is_dep_weight
      + stat_cost * stat_cost_weight
      + dyn_cost * stat_cost_weight
      + integ_cost * integ_cost_weight</pre>
  <p id="oFGI">Что есть что:</p>
  <ul id="dxuY">
    <li id="FMAP">сpu_util - утилизация CPU</li>
    <li id="XWz3">ram_util - утилизация RAM</li>
    <li id="Ptud">is_dep - поставляется отдельной зависимостью или нет</li>
    <li id="2OY0">stat_cost - величина статической стоимости</li>
    <li id="dlcX">dyn_cost - величина динамической стоимости</li>
    <li id="14rb">integ_cost - величина стоимости внедрения</li>
    <li id="8Z9b">_weight - это веса из таблиц с <a href="#sqID">критериями оценки</a></li>
  </ul>
  <pre id="mwXz" data-lang="latex">rsa_score = 2*3 + 2*2 + 0*2 + 0*2 + 1*3 + 1*1 = 14

ed25519_score = 1*3 + 1*2 + 0*2 + 0*2 + 1*3 + 1*1 = 9

gost3410_score = 3*3 + 3*2 + 1*2 + 0*2 + 1*3 + 1*1 = 21</pre>
  <h2 id="wzwx">Выводы</h2>
  <p id="AMyU">Лучшее решение обладает меньшей оценкой. Из приведённых расчётов к такому относятся <strong>Ed25519</strong>.</p>
  <p id="Snlq"><strong>ГОСТ Р 34.10</strong>, сравнивая со всеми остальными решениями, обладает наибольшей утилизацией, как CPU, так и RAM.<br />Стоимость использования такого решения будет оставаться высокой.</p>
  <p id="4ohF"><strong>RSA c 2048 битным ключом</strong> утилизирует аппаратные ресурсы заметно слабее, но на порядок выше, чем это делает <strong>Ed25519</strong>.</p>
  <h2 id="j6JZ">PS</h2>
  <p id="q2lq">Прочитав эту статью, надеюсь, вы начнёте чаще использовать объективный выбор и его же требовать от руководителей, что должно сократить число богемы в мире ИТ 😎</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://leprosus.ru/kiss-principle</guid><link>https://leprosus.ru/kiss-principle?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus</link><comments>https://leprosus.ru/kiss-principle?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus#comments</comments><dc:creator>leprosus</dc:creator><title>Принцип KISS - Keep It Simple, Stupid</title><pubDate>Wed, 20 Nov 2024 15:09:57 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/f4/6d/f46d1d66-e412-4bd5-9cc3-a8e47e2ad145.png"></media:content><category>Принципы</category><description><![CDATA[<img src="https://img4.teletype.in/files/f9/0a/f90a86a9-47f8-4675-a1cb-1a4736d44444.png"></img>Принцип KISS был разработан ВМС США в 1960 году.]]></description><content:encoded><![CDATA[
  <p id="skUd">Принцип <strong>KISS</strong> был разработан ВМС США в 1960 году.</p>
  <p id="qjbs">Он гласит: простые системы будут работать лучше и надежнее.</p>
  <figure id="TKtE" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/f9/0a/f90a86a9-47f8-4675-a1cb-1a4736d44444.png" width="1344" />
    <figcaption>Американские первооткрыватели реликта KISS</figcaption>
  </figure>
  <p id="S8DM">Применительно к разработке ПО принцип означает: не придумывай к задаче более сложного решения, чем ей требуется.</p>
  <p id="4GIt">Во время разработки сложного проекта часто приходится сталкиваться с избыточно сложной реализацией. Наш мозг плохо справляются с нахождением решения для комплексной задачи. Чтобы уменьшить сложности, необходимо разделить задачу на мелкие простые задачи и решать их последовательно.</p>
  <p id="jQ7J">Перефразирую социального психолога <strong>Гюстова Лебона</strong>:</p>
  <blockquote id="U1nd">Мамонта нужно есть по кусочкам</blockquote>
  <h2 id="BD16">Пример</h2>
  <p id="tAZX">У большинства серверного ПО есть пользовательская авторизация. Это некий компонент, отвечающий за управление доступами пользователей. Он может взаимодействовать с другими компонентами системы, чтобы разрешать или запрещать ту или иную функциональность для конкретного пользователя.</p>
  <p id="bnxJ">Разделяя систему на простые компоненты, можно реализовать систему, которая будет состоять из простых и неделимых, отвечающих за определенные действия. Такие компоненты можно организовать в отдельные небольшие блоки кода, каждый из которых будет решать только узкую задачу.</p>
  <blockquote id="fgDb">Для решения декомпозиции комплексной задачи следует использовать принцип <a href="https://ru.wikipedia.org/wiki/Проблемно-ориентированное_проектирование" target="_blank">DDD(Domain-driven design)</a>.</blockquote>
  <h2 id="uCjS">Причина появления</h2>
  <ul id="jFTV">
    <li id="1fZm">Низкая квалификация разработчика</li>
    <li id="D0NH">Когда обучение происходит на базе онлайн-курсов, а не фундаментальных знаний/книг</li>
    <li id="dcBt">Когда нет системного мышления</li>
    <li id="zhaA">Когда сроки реализации функциональности сокращены доне́льзя</li>
  </ul>
  <h2 id="XTf0">Почему сложные решения - это плохо</h2>
  <ol id="t701">
    <li id="lfO8"><strong>Сложность сопровождения</strong></li>
    <ul id="TEvT">
      <li id="dKMF">Нужно затрачивать ощутимо больше времени на перечитывание сложного кода</li>
      <li id="iHfC">Страх у другого разработчика менять код, который он не понимает или понимает плохо</li>
    </ul>
    <li id="PYlb"><strong>Стоимость разработки/сопровождения</strong></li>
    <ul id="3kv0">
      <li id="lHl2">Нужно потратить ощутимо больше времени для понимания и потом для изменения кода, а время разработчика стоит дорого</li>
    </ul>
    <li id="bc5z"><strong>Когнитивное усложнение кода</strong></li>
    <ul id="C1nE">
      <li id="IW49">Так уж устроен наш мозг, что после когнитивно сложной задачи ему нужно немного отдохнуть. В течение времени, который мозг выделил себе на отдых, а это делает именно мозг, а не воля его владельца, его владелец не сможет эффективно переключить его работу на новую задачу, как следствие, владелец начинает прокрастинировать.</li>
    </ul>
  </ol>
  <h2 id="ZYny">Как обнаружить проблему</h2>
  <ul id="zKJv">
    <li id="YSXB">Если для понимания кодовой базы не достаточно бегло пробежать глазами по нему, требуется перечитывать или доставать старый ойуунский бубен и стучать в него;</li>
    <li id="XKpS">Если функция/метод содержит больше 50 строк (тут важна не сама цифра, а понимание порядка);</li>
    <li id="eN1N">Если функция/метод состоит из 5 аргументов (тут тоже цифра может изменяться в зависимости от ЯП, для низкоуровневых языков и 3 аргумента может оказаться сложным)</li>
    <li id="u1hC">Если код необходимо пояснять комментариями</li>
    <li id="ec9E">Когда требуется открыть большое количество скриптов, чтобы понять реализованную функциональность</li>
    <li id="wuXA">Когда сопровождение и/или развитие кодовой базы требует значительного вложения человеко-часов</li>
  </ul>
  <h2 id="SLgr">Как исправить проблему</h2>
  <ul id="Uu9K">
    <li id="Y00R">Разбить код на небольшие короткие блоки, которые выполняют простые атомарные действия</li>
    <li id="JChu">Сложный код разбить на группу простых функций/методов</li>
    <li id="Cdwv">Провести рефакторинг наименования, дать говорящие названия (функции/методы должны говорить, что они делают и в каком контексте, например: getUserByEmail вместо userEmail, переменные должны иметь понятные читаемы названия и не требовать комментариев, например: sortedUsersByLastVisit вместо users)</li>
    <li id="X5dh">Воспользоваться статичтическими анализатора кода с максимально чувствительными настройками и исправить код по его рекомендациям</li>
    <li id="LyYD">Просканировать кодовую массу анализаторами, которые рассчитывают <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity" target="_blank"><strong>cyclomatic complexity</strong></a> и <a href="https://en.wikipedia.org/wiki/Cognitive_complexity" target="_blank"><strong>cognitive complexity</strong></a></li>
    <li id="6u9M">Запросить <strong>code review</strong> у коллег или друзей, чтобы получить альтернативное мнение о коде</li>
  </ul>
  <p id="rzB8">Подходов и решений для профилактики данной проблемы много, главное помнить о необходимости придерживаться данного принципа.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://leprosus.ru/user-story-methodology</guid><link>https://leprosus.ru/user-story-methodology?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus</link><comments>https://leprosus.ru/user-story-methodology?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus#comments</comments><dc:creator>leprosus</dc:creator><title>Методология User Story</title><pubDate>Thu, 14 Nov 2024 20:28:15 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/bb/ee/bbee2527-796e-44d5-9f47-17cd6d8f80fc.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/5e/46/5e46d3b0-5cf1-4eaf-9f49-1d85face717e.jpeg"></img>User Story (пользовательская история) - это методология, используемая в разработке программного обеспечения для описания функциональных требований с точки зрения конечного пользователя.]]></description><content:encoded><![CDATA[
  <p id="SStF"><strong>User Story (пользовательская история)</strong> - это методология, используемая в разработке программного обеспечения для описания функциональных требований с точки зрения конечного пользователя.</p>
  <figure id="O7qo" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/5e/46/5e46d3b0-5cf1-4eaf-9f49-1d85face717e.jpeg" width="4000" />
    <figcaption>Когда по привычке бумагу используешь по назначению</figcaption>
  </figure>
  <p id="f6jc">Подход помогает командам сосредоточиться на потребностях пользователей и создавать более ценные и удобные продукты.</p>
  <p id="RjsM">Также повышается прозрачность передачи информации от заказчика вперёд по цепочке производства вплоть до доставки функциональности на прод.</p>
  <h2 id="Zsnn">Проблемы ТЗ для продуктовой разработки</h2>
  <ol id="wXlO">
    <li id="wyyX"><strong>Потеря ценности</strong></li>
    <ul id="9AIo">
      <li id="rE9D">При передаче бизнес требований от одного человека к другому низкоописанные требования будут заполнены фантазиями и галюцинациями исполнителя.</li>
    </ul>
    <li id="VSHt"><strong>Трата времени</strong></li>
    <ul id="P8sP">
      <li id="loCn">Для повышения понимания поставленной задачи исполнителям нужно будет больше коммуницировать с заказчиком.</li>
    </ul>
    <li id="hHc7"><strong>Потеря качества</strong></li>
    <ul id="qnuH">
      <li id="7kfv">Невозможно низкодекомпозированную задачу реализовать без потери всех аспектов.</li>
    </ul>
  </ol>
  <h2 id="7gdt">Основные компоненты User Story</h2>
  <p id="7Nli">Пользовательская история обычно включает следующие элементы:</p>
  <ol id="SB0w">
    <li id="zwSq"><strong>Роль пользователя</strong></li>
    <ul id="57x9">
      <li id="I6hg">Кто является конечным пользователем (например: покупатель, продавец-консультант).</li>
    </ul>
    <li id="ltCh"><strong>Действие</strong></li>
    <ul id="buhB">
      <li id="Ud7Z">Что пользователь хочет сделать (например: купить товар со скидкой 11.11, повысить продажи во время акции 11.11).</li>
    </ul>
    <li id="0tm3"><strong>Цель</strong></li>
    <ul id="IEAR">
      <li id="m7TB">Зачем это нужно пользователю (например: закрыть потребность меньшими затратами, обеспечить уровень продаж в низкий сезон).</li>
    </ul>
  </ol>
  <p id="c3Pt">Дополнительно, каждая история должна содержать критерии приемки, которые определяют условия, при которых задача считается выполненной.</p>
  <h2 id="jFtW">Принципы написания User Story</h2>
  <p id="zeKC">Для создания эффективных пользовательских историй часто используется акроним <strong>INVEST</strong>:</p>
  <ul id="OuuZ">
    <li id="Kn5l"><strong>Independent (Независимость)</strong></li>
    <ul id="7SP4">
      <li id="gAWc">Истории должны быть независимыми друг от друга.</li>
    </ul>
    <li id="IGEO"><strong>Negotiable (Обсуждаемость)</strong></li>
    <ul id="5XnR">
      <li id="tCri">Истории должны быть гибкими и поддаваться изменениям.</li>
    </ul>
    <li id="rmB1"><strong>Valuable (Ценность)</strong></li>
    <ul id="Wq3H">
      <li id="7aZA">Каждая история должна приносить реальную/оцениваемую ценность пользователю.</li>
    </ul>
    <li id="j7OR"><strong>Estimable (Оценимость)</strong></li>
    <ul id="d1ZI">
      <li id="tngo">Команды должны быть в состоянии оценить время и усилия для реализации без доп консультаций во время реализации.</li>
    </ul>
    <li id="hN0p"><strong>Small (Маленькие)</strong></li>
    <ul id="xUP5">
      <li id="odVU">Истории должны быть небольшими и реализуемыми в рамках одной итерации/спринта.</li>
    </ul>
    <li id="0qC6"><strong>Testable (Тестируемость)</strong></li>
    <ul id="DuZH">
      <li id="e52R">Наличие четких критериев приемки для проверки успешности выполнения.</li>
    </ul>
  </ul>
  <h2 id="59GV">Процесс создания User Story</h2>
  <ol id="UNVg">
    <li id="u1bS"><strong>Определение целевой аудитории</strong></li>
    <ul id="hWMt">
      <li id="nMOf">Понимание, для кого создается продукт.</li>
    </ul>
    <li id="MvQe"><strong>Выявление потребностей пользователей</strong></li>
    <ul id="Cr6t">
      <li id="RBWi">Сбор информации через интервью и опросы.</li>
    </ul>
    <li id="tEni"><strong>Создание списка User Stories</strong></li>
    <ul id="5n8G">
      <li id="wF37">Формулирование кратких описаний функциональности.</li>
    </ul>
    <li id="yvNc"><strong>Приоритизация историй</strong></li>
    <ul id="9iKJ">
      <li id="94We">Определение наиболее важных задач для пользователей и бизнеса.</li>
      <li id="XFMx">Приоритизация должны строиться на основании одного из методов, исключая субъективизм.</li>
      <li id="Tgm5">Список методов можно <a href="https://vc.ru/marketing/274778-12-metodov-prioritizacii-produktovyh-celei-rice-wsjf-kano-i-prochie" target="_blank">почитать тут</a></li>
    </ul>
    <li id="ka65"><strong>Детализация описаний</strong></li>
    <ul id="3QEr">
      <li id="jIhp">Добавление конкретных неделимых шагов и условий для каждой истории.</li>
    </ul>
  </ol>
  <h2 id="zyoM">Преимущества использования User Story</h2>
  <ol id="3NGV">
    <li id="pyDc"><strong>Улучшение коммуникации</strong></li>
    <ul id="pDFw">
      <li id="VRZl">User Stories способствуют лучшему пониманию требований между командами разработки и заинтересованными сторонами.</li>
    </ul>
    <li id="cn5f"><strong>Итеративная разработка</strong></li>
    <ul id="1HER">
      <li id="16Xj">Истории помогают разбить проект на управляемые части, что упрощает процесс разработки в рамках Agile-методологий.</li>
    </ul>
    <li id="u1bb"><strong>Фокус на пользователе</strong></li>
    <ul id="24xf">
      <li id="18ns">Этот подход позволяет командам лучше понимать ожидания клиентов и адаптировать продукт под их нужды.</li>
    </ul>
  </ol>
  <h2 id="eh5b">Хорошие пользовательские истории</h2>
  <ol id="yA3z">
    <li id="RadS">Я, как пользователь сайта, хочу иметь возможность детально принимать результат рассчёта скидок по акции 11.11</li>
    <li id="GQxU">Я, как пользователь, хочу иметь возможность добавлять товар в список избранных, для того чтобы в дальнейшем быстро находить его.</li>
    <li id="1Nte">Я, как пользователь панели с правами супер-админа, хочу иметь возможность посмотреть список администраторов системы, для того чтобы наглядно видеть тех, кто имеет к ней доступ.</li>
  </ol>
  <h2 id="Ndm5">Плохие пользовательские истории</h2>
  <ol id="zY9v">
    <li id="jPbD">Создать страницу товара.</li>
    <li id="uPHU">Добавить функциональность поиска.</li>
    <li id="nCME">Как пользователь, я хочу, чтобы продукт был лучше.</li>
    <li id="7UvP">Я, как администратор системы, хочу иметь возможность добавлять, редактировать и удалять категории товаров, фильтровать и сортировать их. Я также хочу настраивать права доступа к этим функциям для разных ролей.</li>
  </ol>
  <h2 id="Ueez">Визуализация User Story</h2>
  <p id="yV4g">Для этого существуют несколько подходов, один из самых простых - <strong>User Story Mapping (Карта Пользовательских Историй)</strong>.</p>
  <p id="vZOn"><strong>USM</strong> - это метод визуализации, основанный на User Stories.</p>
  <figure id="40CG" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/da/4b/da4bda16-c65d-43d4-94f7-40122f642024.png" width="2434" />
    <figcaption>Когда GuanoStick тоже инструмент</figcaption>
  </figure>
  <p id="XqFf">Какие действия необходимо выполнить:</p>
  <ol id="gRRv">
    <li id="SrO5">В любом удобном инструменте (<em>Google Sheets</em>, <em>MS Excel</em>, либо специализированных, подготовить шаблон, <a href="https://docs.google.com/spreadsheets/d/1TM1zWtsUYmdToLr3LOoASLIrUwODFuqsRNfla_Bj3rc" target="_blank">вот тут можно забрать пример</a>);</li>
    <li id="Y1N5">Перенести в строку <strong>Users</strong> ранее выявленные пользовательские роли;</li>
    <li id="r9mp">Перенести в строку <strong>Actions</strong> ранее выявленные действия: для каждой роли реализуемых действий может быть несколько;</li>
    <li id="3rFM">Для каждого действия заполнить историю;</li>
    <li id="zCLq">Декомпозировать реализацию истории на цепочку понятных неделимых действий;</li>
    <li id="GspQ">Разбить реализацию таким образом, чтобы действия умещались в возможности команды в рамках релизного цикла.</li>
  </ol>
  <p id="minA">В результате получается понятный, хорошо декомпозированный план, который можно передать в команду производства для реализации без риска столкнуться с неоднозначным прочтением требований</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://leprosus.ru/dry-principle</guid><link>https://leprosus.ru/dry-principle?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus</link><comments>https://leprosus.ru/dry-principle?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=leprosus#comments</comments><dc:creator>leprosus</dc:creator><title>Принцип DRY - Don’t Repeat Yourself</title><pubDate>Tue, 12 Nov 2024 20:38:39 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/5d/5c/5d5c66af-212a-4c59-a60b-7c29ef4f8e52.png"></media:content><description><![CDATA[<img src="https://img3.teletype.in/files/60/5d/605d3b63-3572-4046-9a2e-1197297b56ee.jpeg"></img>В чём суть: необходимо избегать повторений одного и того же кода.]]></description><content:encoded><![CDATA[
  <p id="mIDQ">В чём суть: необходимо избегать повторений одного и того же кода.</p>
  <p id="6RUF">И казалось бы, тут всё просто и можно на этом пост завершить. Но вы даже представить себе не можете, как часто этот принцип нарушается даже разработчиками, занимающими высокие позиции в компаниях.</p>
  <figure id="IWGp" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/60/5d/605d3b63-3572-4046-9a2e-1197297b56ee.jpeg" width="2000" />
    <figcaption>Когда горит жопа у плохого разработчика от своего же кода</figcaption>
  </figure>
  <h2 id="gxus">Ретроспектива</h2>
  <p id="CTPI">Впервые принцип был описан <strong>Энди Хантом</strong> и <strong>Дэйвом Томасом</strong> в книге «Программист-прагматик: путь от подмастерья к мастеру» 1999 года <a href="https://en.wikipedia.org/wiki/The_Pragmatic_Programmer" target="_blank">ISBN 978-0135957059</a></p>
  <p id="ykXi">Данный принцип по сути переосмысление <strong>SSOT</strong> - <strong>Single Source Of Truth</strong>.</p>
  <blockquote id="ci6u"><strong>Википедия: </strong>В проектировании и теории информационных систем единый источник истины (<strong>SSOT</strong>) – это практика структурирования информационных моделей и схемы данных, которая подразумевает, что все фрагменты данных обрабатываются (или редактируются) только в одном месте. <strong>SSOT</strong> предоставляют достоверные, актуальные и пригодные к использованию данные.</blockquote>
  <h2 id="jzzj">Причина появления</h2>
  <ul id="Guz2">
    <li id="FR4S">Автор кода обладает низкими профессиональными навыками</li>
    <li id="c5z7">Чаще всего дубли кода появляются в случае, когда разработчик слабо знаком с изменяемой им системой</li>
  </ul>
  <h2 id="21tc">Почему повторяемый код плох</h2>
  <ol id="SkVE">
    <li id="eXlr"><strong>Сложность сопровождения</strong></li>
    <ul id="fejL">
      <li id="P4oi">Автору кода необходимо держать в памяти все места дублей, когда требуется сделать модификацию одного из, иначе поведение в одном блоке изменится, в оставшихся нет.</li>
      <li id="ggad">Если же код сопровождает не автор, то уровень сложности возрастает кратно, так как кроме описанного выше, разработчику придётся ещё догадаться, что код требует изменение кода в нескольких блоках.</li>
    </ul>
    <li id="rJ3K"><strong>Стоимость разработки/сопровождения</strong></li>
    <ul id="9MIx">
      <li id="EHQD">Для реализации кода нужно потратить больше времени на дублирование</li>
      <li id="jwIF">Нужно потратить больше времени для изменение кода, а время разработчика стоит дорого</li>
    </ul>
    <li id="kESl"><strong>Когнитивное усложнение кода</strong></li>
    <ul id="kQAA">
      <li id="3cC1">Читать мутную кодовую базу с дублями для мозга сильно непростая задача</li>
    </ul>
  </ol>
  <h2 id="4nDI">Как можно обнаружить проблему</h2>
  <ul id="whH7">
    <li id="IcUh">Популярные IDE могут показывать дубли кода</li>
    <li id="hHgs">Изменяя алгоритм или поведение, приходится менять код в нескольких местах</li>
  </ul>
  <h2 id="G60h">Как исправить проблему</h2>
  <ul id="0jlv">
    <li id="hVvE">Применять правило &quot;осмотритесь&quot;: перед реализацией нужно убедиться, что новая функциональность ещё не была реализована</li>
    <li id="FaVH">Просканировать код средствами статического анализатора кода, коих во всех языках достаточно, и выискать дубли</li>
    <li id="rEww">Вынести дублируемый код в отдельную функцию и в местах дублирования использовать уже эту функцию</li>
    <li id="T4NQ">Если же код сложнее, чем вынос в отдельную функцию, следует подобрать абстракцию</li>
  </ul>

]]></content:encoded></item></channel></rss>