2) С точки зрения авторов кода раунд так же что-то состоящее из итераций.
/ Round 1 — iterations 0-16 take their input from 'block' /
3) То есть мы не понимаем смысла манипуляций там. Как мы тогда можем утверждать, что от разбиения на куски код станет непонятнее? Надо понять алгоритм — что там зачем и почему и тогда можно сделать функции с читаемыми названиями.
1) var array = first_16_iterations(inputData)…
2) Чем они друг от друга отличаются? Там есть еще итерации внутри раундов. Есть у них какое-то предназначение?
3) Как появилась эта константа и почему она именно такая?
Т.е. вы понимаете смысл того, что там или фактически выполняете работу компилятора, перенося код из книжки на C и оптимизируя его?
Почему не объяснить компилятору, дебаггеру и IDE, что это отдельные стадии, какие переменные используются только внутри стадии, а какие используются для передачи значения между ними? Дебаггер и стектрейс покажет вам на какой стадии вы находитесь, компилятор проконтроллирует, что вы случайно не переиспользовали переменную не предназначенную для этого.
И профайлер вам покажет, сколько какая стадия жрет ресурсов
Там есть комменты, которые разбивают
1) Эту функцию на на куски
2) Описывают взаимосвязи между кусками типа
/*
Where do we get the source from? The first 16 iterations get it from
the input data, the next mix it from the 512-bit array.
*/
Вопрос,
1) почему эти взаимосвязи нельзя выразить явно в коде? Будет ли от этого понятней?
2) Есть ли какое-то предназначение у раундов?
3) Как это все было разработано? Что было в голове у автора и как он взял все эти числа? Нельзя ли это выразить конструкциями языка. Я не спец в крипто — вы можете побыть доменным экспертом?
Самое простое что можно делать это взять код, и приписать сверху то, что вам надо. Правда, результат будет сложным. Сделать так, чтобы результирующий код был простым сложнее — надо разобраться в том, что вам надо и что уже сделано до вас и отрефакторить чтобы результат был простым.
Абстракции — это хорошо. Ровно до тех пор, пока они уменьшают объём кода. И не стоит забывать, что объём кода — это и ментальная нагрузка. Если вы разбиваете код на много мелких частей, то не стоит забывать о сложности связей между этими частями.
Вопрос, какой объем кода считается — общий? Или на конкретном уровне абстракции?
Разбиение документа на части заголовками увеличивает объем, но разобраться в результате проще, потому, что на верхнем уровне есть ограниченный объем глав, и можно понять где заканчивается конкретная глава.
Once I accepted this principle, I developed a habit of writing very small functions — typically only a few lines long [2]. Any function more than half-a-dozen lines of code starts to smell to me, and it's not unusual for me to have functions that are a single line of code [3]. The fact that size isn't important was brought home to me by an example that Kent Beck showed me from the original Smalltalk system. Smalltalk in those days ran on black-and-white systems. If you wanted to highlight some text or graphics, you would reverse the video. Smalltalk's graphics class had a method for this called 'highlight', whose implementation was just a call to the method 'reverse' [4]. The name of the method was longer than its implementation — but that didn't matter because there was a big distance between the intention of the code and its implementation.
Я имел ввиду, что для того, чтобы сделать какие-то изменения в системе — надо в ней разобраться хоть чуть-чуть. Вам пришло задание на доработку вы разбираетесь и после вас остаётся код в чуть более лучшем состоянии чем ты до вас. Потому что пока разбираетесь, то переименовывание и так далее
Хорошо, я думаю надо стремиться к тому, чтобы вынесенное в отдельный класс было доменной абстракцией (может быть какого-то внутреннего технического домена) — то есть отдельным компонентом
Я согласен про "не может существовать отдельно" но не согласен про "единственный экземпляр".
Например энумератор не стоит тестировать отдельно от коллекции, правда, захочется вывести в отдельный раздел "тесты энумератора" который логично назвать MyCollectionEnumeratorTest что сожет совпасть с именем класса энумератора, но этот класс там не будет использоваться напрямую.
Если у нас есть, допустим, компонента которая делает расчет и записывает его в БД то расчет вынести отдельно и тестировать его без БД. Хотя расчет можно нигде не использовать но его использование может быть мыслимо.
Я редко читаю сполошняком все, обычно сначала на первом уровне, потом только для интересных мне мест спускаюсь на уровень ниже.
Вот вы видите в стектрейсе, что ошибка произошла не строке 666 — это понятнее, чем если ошибка произойдет в строке 666, на стадии 1?
Зачем вы вообще для себя делите на стадии этот код, если строки понятны?
1) Это не так же — неявно что есть вход что выход
2) С точки зрения авторов кода раунд так же что-то состоящее из итераций.
/ Round 1 — iterations 0-16 take their input from 'block' /
3) То есть мы не понимаем смысла манипуляций там. Как мы тогда можем утверждать, что от разбиения на куски код станет непонятнее? Надо понять алгоритм — что там зачем и почему и тогда можно сделать функции с читаемыми названиями.
1) var array = first_16_iterations(inputData)…
2) Чем они друг от друга отличаются? Там есть еще итерации внутри раундов. Есть у них какое-то предназначение?
3) Как появилась эта константа и почему она именно такая?
Т.е. вы понимаете смысл того, что там или фактически выполняете работу компилятора, перенося код из книжки на C и оптимизируя его?
Почему не объяснить компилятору, дебаггеру и IDE, что это отдельные стадии, какие переменные используются только внутри стадии, а какие используются для передачи значения между ними? Дебаггер и стектрейс покажет вам на какой стадии вы находитесь, компилятор проконтроллирует, что вы случайно не переиспользовали переменную не предназначенную для этого.
И профайлер вам покажет, сколько какая стадия жрет ресурсов
Можно безо всякого IDE, если языке поддерживает вложенные функции
из мелких функций — это равиолли http://wiki.c2.com/?RavioliCode
Там есть комменты, которые разбивают
1) Эту функцию на на куски
2) Описывают взаимосвязи между кусками типа
/*
*/
Вопрос,
1) почему эти взаимосвязи нельзя выразить явно в коде? Будет ли от этого понятней?
2) Есть ли какое-то предназначение у раундов?
3) Как это все было разработано? Что было в голове у автора и как он взял все эти числа? Нельзя ли это выразить конструкциями языка. Я не спец в крипто — вы можете побыть доменным экспертом?
Самое простое что можно делать это взять код, и приписать сверху то, что вам надо. Правда, результат будет сложным. Сделать так, чтобы результирующий код был простым сложнее — надо разобраться в том, что вам надо и что уже сделано до вас и отрефакторить чтобы результат был простым.
Если вам о ней удобно думать, как о разбитой на пять стадий, а не на 90, почему бы это разбиение не выразить явно в коде?
Вопрос, какой объем кода считается — общий? Или на конкретном уровне абстракции?
Разбиение документа на части заголовками увеличивает объем, но разобраться в результате проще, потому, что на верхнем уровне есть ограниченный объем глав, и можно понять где заканчивается конкретная глава.
Делать просто сложно :) делать просто — нарушает KISS
https://martinfowler.com/bliki/FunctionLength.html
То есть этот код должен быть покрыт тестами внешнего интерфейса, правильно?
Логика, которая в нем содержится, должна быть протестирована или нет?
Это и есть переписать. Только не за один раз. Когда куча мелочей будет решена, последующие задачи будут легче.
И те вещи которые меняются, будут потихонечку переписаны.
Я имел ввиду, что для того, чтобы сделать какие-то изменения в системе — надо в ней разобраться хоть чуть-чуть. Вам пришло задание на доработку вы разбираетесь и после вас остаётся код в чуть более лучшем состоянии чем ты до вас. Потому что пока разбираетесь, то переименовывание и так далее
Пока "разбираешься" в ходе решения текущей задачи записываешь то, в чем разобрался в виде более ясного кода.
Хорошо, я думаю надо стремиться к тому, чтобы вынесенное в отдельный класс было доменной абстракцией (может быть какого-то внутреннего технического домена) — то есть отдельным компонентом
Я согласен про "не может существовать отдельно" но не согласен про "единственный экземпляр".
Например энумератор не стоит тестировать отдельно от коллекции, правда, захочется вывести в отдельный раздел "тесты энумератора" который логично назвать MyCollectionEnumeratorTest что сожет совпасть с именем класса энумератора, но этот класс там не будет использоваться напрямую.
Если у нас есть, допустим, компонента которая делает расчет и записывает его в БД то расчет вынести отдельно и тестировать его без БД. Хотя расчет можно нигде не использовать но его использование может быть мыслимо.