Обновить
8
0
Толмачёв Дмитрий@FiresShadow

Разработчик ПО

Отправить сообщение
Мне кажется, что пример сотрудника, которому повысили зарплату на втором месяце и не повысили спустя год — не очень удачный пример негативных последствий непроясненности ожиданий, потому что 1)прояснение ожиданий, на мой взгляд, в конкретно данном случае будет иметь более негативные последствия, 2)здесь можно говорить не о недосказанности ожиданий, а об обмане ожиданий.

Факт 1. Поскольку сотрудник НЕОДНОКРАТНО «отжёг» там, где не справились другие, то можно говорить, что с 99,9% вероятностью дело в том, что сотрудник имеет уникальные навыки, отсутствующие у других программистов. Скорее всего это умение разбираться в чужом коде в совокупности с коммуникабельностью, и эти навыки полезны не только в начале работы в компании, но и на протяжении всей карьеры программиста.

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

Факт 3. Особенность русского менталитета такова, что русский человек больше внимания уделяет поступкам, нежели словам. Процитирую отрывок только что приведенной статьи: «я не утверждаю, что в других странах людям плевать на поступки менеджеров. Они чрезвычайно важны для всех. Просто наши понимают только их. Слова не работают.»

Из всего вышесказанного получается, что своей непоследовательностью управленец обманул ожидания работника. Однако что было бы, если он сразу прояснил ожидания работника? Что было бы, если бы он сказал: «Знаешь, я даю тебе повышенную зарплату во втором месяце, чтобы произвести на тебя хорошее первое впечатление, чтобы ты, жгущий сотрудник с уникальными навыками, не убежал на другое место работы после испытательного срока, поняв что у нас в вопросе зарплаты действует правило уравниловки. А оно действует. Так что какими бы ты навыками не обладал, сколь эффективным бы ты не был, не жди зарплату, отличающуюся от зарплаты других.» В самом деле, такое лучше не говорить. Почему я посчитал, что у них действует правило уравниловки? По этой строке
Дай, думает, дам ему $3,000, как всем.
Получается, что управленец поступил на самом деле скорее продуманно: заимел хорошего сотрудника по цене обычного (человеку, когда он проработал год, сложнее уйти, чем когда он проработал 2 месяца), человек был хорошо мотивирован в течение года (а демотивирован он может быть и меньший срок), у человека в его сознании, возможно, не оформилась фраза «моя зарплата не зависит от моих навыков» (подсознательно он может это и понимать, но в сознании этих слов может и не быть, по крайней мере, нужно некоторое время чтобы проанализировать ситуацию и сформулировать словесный тезис).
Конечно, возможен вариант, что управленец не понимает, что у сотрудника есть уникальные навыки и жгёт он не просто так. Но тогда совет «Проясняйте ожидания» не сильно ему поможет, а может даже иногда и навредить (если управленец всем на собеседовании будет рассказывать, что в компании коммунизм и все получают одинаково, то кто пойдёт к нему работать? какие профессиональные и личностные качества будут у этих людей?). Конечно, можно мотивировать людей не только зарплатой, но если управенец, извините, очевидных вещей не понимает, то в этом вопросе у него также будут проблемы. Тут нужно плотно работать с управленцем, объяснять ему придётся много…
Возможно в этой истории есть какие-то недосказанности, которые рушат все мои рассуждения. Например, если уровень зарплаты в организации наивысший в городе, то работнику может быть и не так важно, получает он больше или меньше своих коллег — главное, что он получает больше, чем получал бы на другом месте работы. Тогда ожидания можно и прояснить.
Я согласен, что конфликт возник из-за недосказанности, но считаю, что в конкретно данном случае недосказанность (для управленца) скорее плюс, чем минус (по крайней мере в коротко-срочной и средне-срочной перспективе).
В целом статья супер. Спасибо вам! :)
Всё что вы сказали, уже обсуждалось в комментариях выше, причём очень подробно.
Для криптоалгоритма… необходимо… произвести декомпозицию в соответствии с этим описанием

Проблема как раз в том, что декомпозиция алгоритма в коде должна соответствовать декомпозиции алгоритма на едином языке доменной модели (Ubiquitous Language), а над единым языком программист не имеет власти. Это сказал wheercool в комментарии от 9 октября 2014 в 13:35. Потом на эту тему рассуждали довольно долго.

Для танца логично применить паттерн интерпретатор.

В комментарии от 9 октября 2014 в 18:21 boolivar с целью уменьшения размера метода предлагал завести массив из указателей на функции и в цикле этот массив обходить. Подводя итог обсуждения его предложения, можно сказать, что этот подход предоставляет некоторые преимущества, но за них нужно платить незначительным повышением сложности кода и незначительным уменьшением читабельности, и если не использовать предоставляемые преимущества, то незачем эту цену и платить. Вы предлагаете примерно тоже самое. Думаю, дело ещё и в том, что вы не понимаете, что такое паттерн проектирования. Паттерн — это типовое архитектурное решение типовой проблемы. Знание этого простого определения даёт понимание, когда нужно использовать тот или иной паттерн, а когда — нет. И критерий очень прост — когда есть проблема, то используем паттерн, который её решает, если нет такой проблемы — то, соответственно, не используем. Не нужно писать абстрактную фабрику, если нет сложного алгоритма создания объекта, тип которого зависит от фазы луны (или алгоритм создания зависит от фазы луны). По-хорошему, по мере нахождения не несущих полезной нагрузки абстрактных фабрик, нужно все лишние фабрики фабрик вычищать из кода, дабы не создавали лишней сложности. Точно также, если нет часто встречающейся, но подверженной изменениям задачи, а также если нет языка для интерпретации, предложения которого можно представить в виде абстрактных синтаксических
деревьев, то паттерн Интерпретатор использовать не нужно. Где, скажите пожалуйста, в аборигенском танце есть часто встречающая и подверженная изменениям операция? Присесть и покудахтать — это две совершенно разные операции, а не вариации одной и той же. Синтаксических деревьев тоже нет, алгоритм танца линеен. Или вы хотите выделить интерфейс ДействиеТанца (или вообще интерфейс ДействиеПрограммы, т.к. «присесть» может использоваться не только в танце) с единственным методом Интерпретировать, разбить код на сто-пятьсот маленьких классов (по количеству действий танца) и в функции СтанцеватьАборигенскийТанец создать массив из объектов-действийТанца, и в цикле их обойти? И что, в гигантском массиве копаться проще, чем в гигантской функции? А что вы будете делать, если в одну из функций вдруг понадобится передавать параметры? Перепишете пятьсот классов, потому что они наследуют общий интерфейс, или же будете передавать параметры через конструктор конкретного ДействияТанца? Чувствую, при таком подходе будет или много писанины, или потребуются навыки Шерлока Холмса, чтобы разобраться, что же тут происходит. Лично я никакой пользы не вижу от того, чтобы решать проблему паттерном, который для решение этой проблемы не предназначен. Паттерны проектирования — это, конечно круто, но не следует их использовать где попало. Тоже самое и с фасадом. Где в примере с закупкой сложная подсистема, с которой настолько сложно взаимодействовать, что нужно выносить взаимодействие с ней в отдельный объект? Неужели это функция распарситьЗакупку? Да там даже никаких объектов не создаётся (при условии что парсинг отдельной сущности уникален, но занимает несколько строчек кода. Если же парсинг большой и сложный — выносим его в отдельный класс), просто несколько функций одна за одной вызываются, пусть их количество может быть и велико (в зависимости от количества вложенных в Закупку сущностей на одном уровне абстракции — лотов, протоколов и пр.). К тому же, ну вынесите вы логику распарситьЗакупку в отдельный объект, назовёте его Фасадом, у Фасада будет всего один метод. Заглядываем в этот метод, а там внутри что? Неужели один в один прежнее содержание функции распарситьЗакупку, да ещё создание объекта добавилось? И зачем тогда всё это затевалось?
В эксперименте во втором случае код разбивали на 2 листа или дописывали к первому листу ещё пол-листа?
Действительно, ПрименитьАлгоритмМодифицированногоDESа(данные) — действительно неудачное название для функции. Однако проблема не в том, что это не точный термин, в котором мало конкретики, а как раз наоборот — проблема в том, что в нём СЛИШКОМ много конкретики. Со временем, после множества модификаций, с DES-ом у неё может остаться мало общего. Также в нем могут быть использованы куски других алгоритмов шифрования. Более правильное название в этом случае — ПрименитьСобственныйАлгоритмШифрования(данные). А если в программе только один алгоритм шифрования, и других добавлять не планируется, то можно просто — Зашифровать(данные). Ну и если язык поддерживает ООП, то нужно занести шифрующую и дешифрующую функции в один класс. При этом в названии «Зашифровать» достаточно конкретики, контракт функции предельно ясен — данные преобразуются таким образом, что их практически невозможно восстановить без ключа. При этом как это происходит, пользователю функции не важно.
Ну, модифицировать алгоритм может и не программист. Однако модификации могут происходить в несколько этапов (правки после замеров на практике), поэтому неплохо бы иметь возможность быстро находить нужные куски алгоритма. В этом смысле весь код перед глазами предпочтительнее кода, разделенного непонятно по какому принципу непонятно по каким методам. И да, примеры не из реальной жизни, а специально придуманные для пояснения мысли статьи. Для примера с сайтом нужно немного воображения, примеры с танцем и модифицированным DES-ом могут стать реальными при некотором стечении обстоятельств.
«testCreateFile_shouldThrowException_whenFolderDoesNotExist»

Разве это нельзя назвать user-story?
На самом деле можно было бы и не бросать исключение, а создать директорию, тогда бы размер контракта уменьшился (т.к. избавились от одного предусловия), и функция выполняла бы свои обязанности, если она в состоянии их выполнить, а кидала бы исключение только в случае невозможного имени файла/директории. Если существование директории обязательно, можно отразить это в названии метода, например CreateFileInExistedDirectory, тогда вы дважды подумаете, прежде чем использовать этот метод в случае, если существование директории не обязательно.
А вам не кажется, что вы сами себе противоречите?
«Модифицированный DES» — это тот же «безсистемный танец»… так как мы не специалисты по шифрованию»

А это приводит к ещё одной интересной мысли — не стоит заниматься декомпозицией и выносить действия в отдельную метод не только когда эти действия не имеют общей цели (или имеют, но нам об этом неизвестно), но и тогда, когда действия имеют общую цель, но для осознания этого программисту потребуется больше усилий, нежели сэкономит декомпозиция. В самом деле, может быть шаман в курсе, что приседание и кудахтание вызовет восторг духа горы, а другие четыре действия привлекут внимание духа озера. Но если в планах нет написания серьёзного приложения, умеющего применять множество заклинаний, исходя из знания нужных комбинаций довольных богов, а на самом деле нужно просто сделать робота, владеющего парой танцев, то может ну их, эти аборигенские верования? Точно так же глубокое изучение криптографии, вплоть до понимания что общего у round функций всех шифров (а если нет ничего общего, то это никакая не абстракция), только ради того, чтобы декомпозиция модифицированного DESa приносила пользу, а не вред, — такое понимание тоже вряд ли окупится, если нужно написать всего один шифрующий алгоритм. И даже если вы знаток аборигенских верований и криптографии, для создания хорошего дизайна нужно в первую очередь думать о других программистах.

«Названия не всегда отражают назначение, иногда эта штука служит для запоминания/обозначения»

Я уже описывал вам своё мнение на этот вопрос в комментарии за 11 октября 2014 в 23:22
Лучшая документация — понятные имена переменных и функций, а также стройная и последовательная архитектура. Такая документация никогда не устареет и не введёт в заблуждение, ей приятнее и проще пользоваться. Конечно же, документация по общим архитектурным принципам и стандартам — хорошая практика. Но слишком подробная документация, вплоть до описания контрактов всех сущность, требует много времени на поддержание в актуальном состоянии и склонна быстро устаревать. А от устаревшей, вводящей в заблуждение документации больше вреда, чем пользы.

Юнит-тесты же хороши для описания user-story и для контроля соблюдения контракта, но я никогда не видел хороших примеров описания контракта тестами. Конечно, в редких случаях, когда совсем непонятно что же делает метод, можно посмотреть на тесты и понять, что же он возвращает при некоторых входных параметрах. Однако тогда нужно будет применять дедуктивные способности, чтобы понять, что общего у возвращаемых значений и каковы постусловия метода.

На самом деле подобрать хорошее название методу, чтобы оно описывало контракт, легче, чем кажется. Сначала просто берёте и пишите что делает функция (это важно — что, а не как) со всем контрактом, включая описание требований к параметрам. Может получиться что-то вроде РассчитатьДебетИКредитДляВипКлиентаПроверивПраваНаДоступКДаннымКлиента(клиент). Сразу видно, что функция нарушает принцип единственности ответственности, разделяем её на РассчитатьДебетДляВипКлиента(клиент) и РассчитатьКредитДляВипКлиента(клиент), а проверку прав, как сквозную функциональность, выносим в отдельный аспект. Потом вдруг замечаем, что вторая функция может рассчитать кредит для любого клиента, изменяем её имя на РассчитатьКредит(клиент). РассчитатьДебетДляВипКлиента(клиент) оставляем в таком виде до тех пор, пока не потребуется рассчитывать дебеты для других типов клиентов, тогда можно будет добавить параметр isVip (или использовать полиморфизм), убрав пред-условие виповости клиента из названия. Также убираем из названия функции лишние постусловия, наступление которых очевидно. Если функция имеет название ДобавитьЭлементВКонтейнерУвеличивЕгоРазмерностьНаОдин(элемент), то так как очевидно, что добавление элемента в контейнер повлечёт увеличение размера контейнера на один, то из названия это постусловие убираем, остаётся ДобавитьЭлементВКонтейнер(элемент). Потом вспоминаем, что функция существует не в вакууме, а в классе Контейнер, поэтому урезаем название до ДобавитьЭлемент(элемент). Что именно добавляется понятно из параметров, поэтому остаёте просто Добавить(элемент). Если нет времени заниматься рефакторингом, то лучше использовать длиннющее или неинформативное название, чем обманчивое. Название метода «УзнатьДату» — наихудший выбор из возможных, если метод не только узнаёт дату, но и сохраняет её в бд, а также рассылает пользователям уведомления на почту при её изменении, хотя «УзнатьДату» внешне и выглядит приличнее, чем «ОбработатьДату» или «УзнатьИСохранитьДатуИУведомитьПользователейПриЕёИзменении».
Советы, как говорится, «от капитана очевидности», но может быть кому-нибудь окажутся полезными.
«По какому угодно имени нельзя понять контракт можно только угадать его часть»

Лично у меня редко возникают сложности с тем, чтобы уместить контракт в фразу максимум из 6 слов (но обычно слов меньше, длинные названия в основном в тестах и описывают user story, проверяемые тестами), и по названию функции понятно что функция делает, и какие у этого последствия тоже ясно, поэтому и конструкции вида Contract.Assert() я редко использую.

«Если кусок 1 не будет оформлен как функция, мы будем знать о контракте меньше»

Не вижу сложностей с тем, чтобы заинлайнить метод с ничего не выражающим именем и не потерять сведений о контракте этого куска кода. Поскольку название ничего не выражало, то эта часть контракта не теряется (т.к. её и не было). Конструкции вида Contract.Assert() инлайнятся вместе с кодом.
«если есть устойчивое сложившееся название это может окупить его неправильность»
Именно так я и сказал в своей статье. Перечитайте пример с модифицированным DES-ом. В очередной раз повторюсь, что там мы немного модифицируем «Функцию Фейстеля», после чего она «Функцией Фейстеля» не является, так же мы модифицируем и некоторые другие места, поэтому устойчивых сложившихся названий в модифицированном DES-е нет.

«постепенно изучая давать более удачные обозначения»

Перечитайте то место в статье, где говорится, что метод плохо поддаётся декомпозиции, если «не получится объединить некоторые из них (строчки кода) в отдельную функцию с понятным именем». Повторюсь в очередной раз и дам более подробные объяснения. Есть метод «Узнать информацию о закупке», на наивысшем уровне абстракции у него одна операция — получить информацию о закупке, на уровне абстракции пониже (далее — верхний уровень) — столько операций, сколько внутри закупки других сущностей, информацию о которых нужно узнать. Т.е. там внутри 1)узнать информацию о лотах закупки 2)о протоколах 3)о отзывах 4)о прогнозах 5)о поставщике, и ещё много чего. И каждая строчка кода имеет цель, никак не связанную с другими строчками кода на верхнем уровне абстракции. Если бы была связь, то их можно и нужно было бы объединить в отдельный метод. А если нет связи, то не нужно объединять. А если вы всё-таки объедините в один метод и дадите методу имя «Кусок1», то сколько не думайте, удачного названия не найдёте — решаемые то задачи кода не изменятся от того, что вы провели декомпозицию.

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

Допустим, «Кусок1» изменяет состояние класса так, что это нарушает контракт «Куска2». Или результат вычислений «Куска1» передаётся в «Кусок2», нарушая его контракт. Как понять по названию «Куска2», какой у него контракт? Да никак. Второй пример — «Кусок1» был модифицирован, после чего оказалось, что «Подкусок1» из «Куска2» стал очень похож на «Кусок1». Не один в один, но если подумать немного, то можно сделать параметризацию и вынести дублирующийся код в отдельный метод. Как, даже имея перед глазами подробную UML-диаграмму, вы поймёте, что «Кусок1» и «Подкусок2» похожи? Никак. Если вы сводите на нет читаемость и самодокументированность кода только потому, что «что-то метод длинноват», то не ждите, что это останется без последствий.

«за счет выноса шифрования блока в отдельную функцию и лаконичных обозначений в стиле Pythion»

Вам удалось создать одну удачную абстракцию — Блок. Но вот функция «зашифровать блок» как раз таки будет большой. Я и не подразумевал, что весь модифицированный алгоритм DES-а нужно делать в одну функцию, наверняка получится выделить ещё абстракцию «Перестановка», принимающая в качестве параметра блок и матрицу перестановок. Но вот внутри модифицированного DES-а будут большие методы (зашифровать блок). Абстракция «Зашифровать полублок» — неудачная, т.к. полублок вы дешифровать не сможете (без второго полублока). Текст шифруется блоками, а не полублоками. По сути, метод должен называться «Произвести с полублоком действия, необходимые для шифрования блока». Название метода ничего не отражает, т.к. это итак ясно из контекста использования. А если бы в блоке каким-то чудом была матрица, вектор и лопасть вертолёта, вы бы предложили выделить методы «Сделать что-то с МатематичПонятиями» и «Сделать что-то с ЛопастьюВертолёта»? Мне не нравится такой дизайн, а почему — я уже говорил неоднократно.

К слову, у вас очень хорошо получается обращать внимание на недосказанности и двусмысленные места, возможно, благодаря вам, я научусь выражать свои мысли очень точно. Спасибо вам :) Добавлю с статью какой именно метод в модифицированном DES-е, по моему мнению, должен быть большим
Перечитал свой ответ на ваш комментарий, и понял что он недостаточно подробно отвечает на главный ваш вопрос.

«Тут вопрос, что лучше, если не знаешь как придумать название — не давать никакого и не делать никакой структуры или дать какую-то структуру.»

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

Ну да ладно, в очередной раз повторюсь. Как говорится, повторение — мать учения.
Если вы каждый день работаете с кодом, то поневоле вы может и выучите, что есть в «Куске1», а что в «Куске2». Но раз вы наизусть знаете алгоритм, то если содержимое «Куска1» и «Куска2» вставить в одно место, то вы всё равно найдёте нужное вам место. А вот если пришёл новый разработчик на проект, то он видит кучу методов с ничего не выражающими для него именами, при этом код разбит на мелкие процедуры и ветвист. Ему нужно обходить дерево кода как лабиринт. Или вот хочет новый разработчик внести изменения в «Кусок1», но сомневается как это повлияет на «Кусок2», заходит он в «Кусок2», а там «Подкусок1» и «Подкусок2»… Работать в таких условиях очень тяжело. Разбор кода идёт медленно, при кодировании часто допускаются ошибки. Автору то кода и названий может и хорошо живётся, более того, он — «Незаменимый программист», потому как никто «почему-то» не может нормально работать с тем что он понаписал, а поддерживать и сопровождать всё это надо, поэтому «Незаменимый программист» — ценный сотрудник. Более того, создаётся ложное впечатление, что «Незаменимый программист» более опытный, потому как он может, а другие почему-то — нет.
«со временем слово лопата запомнится и станет привычной»

Похоже, всё дело в том, что не понимаете что такое Абстракция. Абстракция — это отвлечение от несущественных сторон, с целью выделения существенных, закономерных признаков. Ну вот разбили вы алгоритм на «Кусок1» и «Кусок2», каждый из кусков используется только один раз. Какой у «куска1» закономерный признак? Он используется в модифицированном DES-e. Ну и что, второй тоже там используется. Нет закономерных признаков — нет абстракции. Кроме того, ваша «абстракция» и место где она используется в вашем случае — одно и тоже. Тому, кто будет сопровождать ваш код, эта «абстракция» никак не поможет — чтобы понять что это такое, нужно посмотреть что внутри метода. А чтобы понять что там внутри, нужно проваливаться внутрь метода. Это вредит дизайну программу, а почему вредит — я подробно рассматривал в статье.
«Почему авторы статьи википедии считают, что понятнее разбить алгоритм на этапы, а вы, не понимая самого алгоритма решили что лучше написать одной большой простыней не давая этапам никакого названия.»
«зачем вы уничтожили эту структуру в своем псевдокоде?»

Я вот только что, в 18-15 дал ответы на все эти вопросы, а вы в 18-47 снова их задаёте, только вставляете их так, чтобы они были выше в ветке комментариев. Скажите честно, вы — тролль?

Повторюсь в очередной раз, 3й пример — это немного модифицированный DES, а не сам DES.
«вы зачем-то переносите из википедии код не 1-в-1 а инлайня функции»

Это было сделано намеренно. Первая цель — показать, как авторы самого алгоритма занимались декомпозицией. Вторая цель — так как мы модифицируем алгоритм, содержимое «функции Фейстеля» изменяется, и это больше не «функция Фейстеля» (т.к. она делает другие операции). Соответственно, мы не можем использовать ту же самую декомпозицию и туже самую абстракцию, что использовали авторы DES, и толк от неё теряется.

«Циклы шифрования»
Что выражает название метода «Циклы шифрования»? Что это что-то, как то связанное с шифрованием и что внутри есть цикл. То что это связано с шифрованием, итак ясно из контекста использования метода. То что в названии функции отражено что внутри есть цикл — это вообще нарушение инкапсуляции. Это как раз пример плохой синтетической абстракции, о которой я говорил ранее. Это всё равно что дать методу имя «Сделать хорошо», а классу — «Manager» или «Service». Эти названия ничего не отражают.
«Настоящие авторы метода написали непонятно»

То что для одного непонятно, для другого — очевидно. Программист в своей карьере может сталкиваться с различными предметными областями, и на освоение всех из них в совершенстве ему просто не хватит жизни. Вот вы понимаете, почему ядро атома не разлетается на кусочки в то время как внутри него действуют чудовищные отталкивающие силы? А если вас попросят запрограммировать модель атома, будет ли для вас проблемой то что вы это не понимаете, точно также, как для вас проблема, что вы не понимаете почему в DES-е 16 итераций? Нет, вы скорее всего просто возьмёте и запрограммируете.

«То есть в данном случае «длинный метод = проблема» срабатывает»

Было бы неплохо, если бы вы хоть как-то обосновывали свою точку зрения. Наверное, вы считаете, что так как а)«Чем меньше метод, тем он понятнее» и б)«Этот метод непонятный», ТО «если понаделать мелких методов, станет понятнее». Или, может быть, вы считаете, что «раз алгоритм не дробится на мелкие части, то это плохой (непонятный) алгоритм». На самом деле, непонятный не значит плохой, непонятный тут значит чуть сложнее обычного. Ну вот встречаются в природе такие алгоритмы, у которых на верхнем уровне абстракции много действий, и ничего с этим не поделать, кроме как самому напридумывать синтетических абстракций. Самый простой способ эти абстракции придумать — разбить алгоритм на «Функция имени меня», «Функция имени вон той планеты», «Функция имени моего домашнего животного», а потом завести книжку с описанием, что в какой функции происходит, потому как «Функция Фейстеля» из DES-а ну никак не отражает содержания этой функции. И если раздробите вы плохо декомпозирующийся алгоритм на части, понятнее он от этого не станет. Примеры я уже приводил.
Хотя, наверное, 16 как-то связано с размерностью блока в байтах и количестве информации, которая в этот блок влазит, но не уверен, так что обманывать не стану
«А то получается, что автор метода не вы»
Вы правы, я не изобретал DES.

«Например, от это 16 раз почему — 16, а не 32 или 7.»
Боюсь, мне понадобится около месяца не ходить на работу и всё это время изучать глубины математики и криптографии, чтобы понять почему 16 итераций цикла посчитали достаточным количеством для достижения необходимого уровня криптостойкости при существующем уровне вычислительных мощностей компьютера, которые могут быть использованы для перебора ключей. После этого вам потребуется примерно такое же время, чтобы понять мои объяснения. Вы согласны договориться с моим работодателем, оплатить материальные издержки и пообещать, что мои усилия не окажутся напрасными и вы будете в этом разбираться? Попросту говоря, я не знаю почему 16 =)
Добавил пример в конец статьи
Тут опечатка. По смыслу понятно, что имеется ввиду апи (прочитайте предыдущее предложение)

Информация

В рейтинге
Не участвует
Откуда
Россия
Дата рождения
Зарегистрирован
Активность