В контексте нервной системы серотонин, дофамин и прочее - нейротрансмиттеры, а не гормоны. Нейротрансмиттеры работают для передачи сигналов в синаптической щели нейронов. Гормоны же являются сигналтными молекулами, воздействующими на рецепторы на поверхности или внутри клетки.
Одно и то же вещество может выполнять одновременно обе функции и гормона и нейротрансмиттера в разных частях организма. Более того некоторые даже по-разному называются из-за этого, потому что исторически были открыты дважды в разных конекстах - Adrenaline, Norepinephrine.
Отличная новость. Ждём комментариев клоуна из какого то опсоса, который в комментариях к одному из постов на эту тему рассказывал, что юзеры, использующие смартфон для раздачи интернета - воры. Хочется посмеяться над аргументацией, о том, как это правильно брать с пользователей арендованного колодца, с безлимитный доступом к воде дополнительную плату в зависимости от типа тары, которой эту воду черпают. Что мол вёдрами норм, а вот если зачерпнул чашкой - то все, извольте отправиться на шконку ну или хотя бы заплатить за этакое бесчестное поведение.
Очень дельные замечания, со многим согласен, но я бы, пожалуй дополнил еще несколькими:
1) Генерируемые данные рассогласованы.
В задании нет четкого указания, на сколько корректными должны быть данные, генерируемые случайным образом. Но мне кажется, что стоило бы обеспечить минимальный уровень согласованности. Возможо, что автор задания хотел проверить детальность проработки задания. Наверно лучше уточнять такие детали перед выполнением задания. Вот, что я бы предположил:
Дата рождения не согласуется с возрастом, генерируются раздельно. Достаточно вычислять возраст на основе случайно сгенерированной даты рождения. Но я бы сделал Age вычисляемым свойством, что правда, противоречит предоставленной структуре класса Person.
Пол не согласуется с именем. Пускай это и в духе современных трендов, но мне кажется, что в данном случае это скорее не заранее продуманная фича.
Возраст детей не согласуется с возрастом родителя. Вполне вероятно, что случайные данные нагенерируют 12-летних детей у которых есть свои дети возрастом под 68 лет.
Фамилия детей не согласуется с фамилией родителя.
Возраст не согласован со статусом вступления в брак. 3 летние женатые дети.
Можно еще кучу ограничений придумать, это то, что пришло в голову с ходу. Возможно стоило бы генерировать сразу целые семьи с супругами и детьми, чтобы согласовывать эти данные.
Не понятно, должен ли идентификатор ребенка Child.Id быть согласованым с Person.Id. Но выглядит так, что скорее всего да. Тогда детей нужно создавать как Person, а родитель должен ссылаться на реальных Person с реальными Id.
2) Нет консистентности в названии классов.
Одни классы называются ***Generation, другие ***Generator. Думаю, что следует придерживаться одного подхода к именованию.
3) Есть такое правило, что если класс помимо конструктора содержит всего один метод, то стоит задуматься, а нужен ли вообще такой класс. Возможно стоит конвертировать его в просто в метод, чтобы не слишком усложнять код и не плодить сущности.
Про то, что плохая практика в конструкторе класса делать "тяжелые" операции, не связанные с инициализацией объекта уже написали.
4) Я бы предложил использовать автоматическое выведение типов (var) в конструкциях, вроде:
JsonWriter<Person> jsonWriter = new JsonWriter<Person>();
JsonReader<Person> jsonReader = new JsonReader<Person>();
Заменил бы на
var jsonWriter = new JsonWriter<Person>();
var jsonReader = new JsonReader<Person>();
Это лучше читается, для такого "масла масленного" этот сахар и был придуман.
5) Вызов метода Dispose() у класса PersonsGenerator.
Класс PersonsGenerator судя по коду из статьи не реализует ни интерфейс IDisposable, ни собственно метод Dispose(). Скорее всего это опечатка, иначе этот код просто бы не работал.
Не понятно, что вообще должен в данном случае делать этот метод, так как очистка PersonsGenerator.persons производится явно, вне данного метода. Вероятно, эту операцию как раз надо засунуть внутрь Dispose(). И тогда использовать генератор вместе с конструкцией using:
using (var personsGenerator = new PersonsGenerator()) { ... }
Но я бы вообще не стал хранить в генераторе сгенерированные данные. Ответственность генератора - генерировать сущености, а не хранить их.
6) Не стоит сохранять в финальном коде отладочные куски, я про это:
// Не обращаем внимание, так, для себя сделал
7) В дополнение к 6), для вывода небольших массивов в отладочной строке можно было бы воспользоваться методом string.Join(), тогда можно было бы элементы массивов выводить через разделитель, например через запятую.
Вообще мне кажется, что тут рефлексия не особенно нужна, можно было бы для класса Person переопределить метод ToString() и в явном виде форматировать данные. Или вообще для отладочного вывода просто печатать готовый json в котором уже произведена почти аналогичная сериализация данных, так сказать бесплатно и без лишнего кода.
8) Мне понравилась обертка для Faker, которая называется Bogus (https://github.com/bchavez/Bogus). Рекомендую посмотреть на ее реализацию создания декларативных генераторов, мне кажется, что это довольно красивое решение, которое иногда избавляет от необходимости написания своих классов-генераторов. Плюс эта библиотека содержит кучу дополнительных расширений, среди которых, например есть возможность генерировать данные для не-англоязычных сред, например имена на русском языке.
Все вышесказанное - мое имхо и не является истиной в последней инстанции, надеюсь какие-то из советов будут полезными, желаю удачи автору статьи с поиском работы!
Удивительно, что ни кто еще не вспомнил про Processing. Мало того, что он создан именно для таких целей (минимальный boilerplate для рисования), так еще реализацию под Java, Python и JavaScript и даже что-то под Android. Поддерживает ввод, легко реализовать, например, рисование мышью, таймеры и даже вроде 3D.
Так в том и засада, что 8 в UTF-8, 16 в UTF-16, означает минимальную длину в битах, которую может использовать кодировка, но при этом ни как не говорит о максимальной длине. Отсюда и лезут ноги у забулждения, что UTF-8 использует один, а UTF-16 два, написано же 8 и 16 бит, а факт того, что вся кодовая таблица UNICODE при всем желании ни в один ни в два байта не влезет во внимание не берется.
Кстати, здесь же в статье есть еще неточность:
Современные операционные системы, как правило, используют UTF-8
Если я правильно понимаю, то Windows вообще по-умолчанию использует Windows-1252 или Windows-1251 (либо другую "локальную" кодировку), а в случае юникода раньше использовалась одна из UTF-16 (little endian / big endian). Поддержка UTF-8, в качестве кодировки по-умолчанию, появилась сравнительно недавно. Но я могу заблуждаться, подробно в этой теме не разбирался.
Современные операционные системы, как правило, используют UTF-8, который кодирует символы одним байтом, а не два байта UTF-16
Это - заблуждение. UTF-8 использует переменное количество байт, от одного до четырёх. Один байт используется в случае кодировки символов из таблицы ASCII. UTF-16, точно так же использует от 1 до 4 байт в зависимости от кодируемого символа.
Назначение результатов работы оператора распаковки переменным
Возможно, после того, как вы узнали о возможностях оператора распаковки, вы захотите пользоваться им для записи данных в переменные. Посмотрим на то, как это сделать:
string = «Let's learn Python»
# Мы собираемся сохранить результат распаковки строки в var1
var1 = [*string]
Возможно, вам покажется непонятной конструкция [*iterable]. Поэтому давайте с ней разберёмся.
Рубрика «Вредные советы». Если вдруг Вам по какой-либо причине захочется воспользоваться оператором * для создания итерируемого объекта другого типа на основе существующего, то нужно просто воспользоваться конструктором нужного типа:
var1 = list(string)
Вместо какой-то нечитаемой конструкции, проблему которой сам же автор признает:
Конечно же не понятно, что сделать-то хотели? Конвертировать строку в список? Ну так и пишите! Вместо list может быть tuple, deque, set или другие коллекции, поддерживающие инициализацию из итерируемого объекта.
В контексте нервной системы серотонин, дофамин и прочее - нейротрансмиттеры, а не гормоны. Нейротрансмиттеры работают для передачи сигналов в синаптической щели нейронов. Гормоны же являются сигналтными молекулами, воздействующими на рецепторы на поверхности или внутри клетки.
Одно и то же вещество может выполнять одновременно обе функции и гормона и нейротрансмиттера в разных частях организма. Более того некоторые даже по-разному называются из-за этого, потому что исторически были открыты дважды в разных конекстах - Adrenaline, Norepinephrine.
А пранансы будут?
Пора заводить реестр!
Подержите мой кагор:
Hidden text
Отличная новость. Ждём комментариев клоуна из какого то опсоса, который в комментариях к одному из постов на эту тему рассказывал, что юзеры, использующие смартфон для раздачи интернета - воры. Хочется посмеяться над аргументацией, о том, как это правильно брать с пользователей арендованного колодца, с безлимитный доступом к воде дополнительную плату в зависимости от типа тары, которой эту воду черпают. Что мол вёдрами норм, а вот если зачерпнул чашкой - то все, извольте отправиться на шконку ну или хотя бы заплатить за этакое бесчестное поведение.
Очень дельные замечания, со многим согласен, но я бы, пожалуй дополнил еще несколькими:
1) Генерируемые данные рассогласованы.
В задании нет четкого указания, на сколько корректными должны быть данные, генерируемые случайным образом. Но мне кажется, что стоило бы обеспечить минимальный уровень согласованности. Возможо, что автор задания хотел проверить детальность проработки задания. Наверно лучше уточнять такие детали перед выполнением задания. Вот, что я бы предположил:
Дата рождения не согласуется с возрастом, генерируются раздельно. Достаточно вычислять возраст на основе случайно сгенерированной даты рождения. Но я бы сделал Age вычисляемым свойством, что правда, противоречит предоставленной структуре класса Person.
Пол не согласуется с именем. Пускай это и в духе современных трендов, но мне кажется, что в данном случае это скорее не заранее продуманная фича.
Возраст детей не согласуется с возрастом родителя. Вполне вероятно, что случайные данные нагенерируют 12-летних детей у которых есть свои дети возрастом под 68 лет.
Фамилия детей не согласуется с фамилией родителя.
Возраст не согласован со статусом вступления в брак. 3 летние женатые дети.
Можно еще кучу ограничений придумать, это то, что пришло в голову с ходу. Возможно стоило бы генерировать сразу целые семьи с супругами и детьми, чтобы согласовывать эти данные.
Не понятно, должен ли идентификатор ребенка Child.Id быть согласованым с Person.Id. Но выглядит так, что скорее всего да. Тогда детей нужно создавать как Person, а родитель должен ссылаться на реальных Person с реальными Id.
2) Нет консистентности в названии классов.
Одни классы называются ***Generation, другие ***Generator. Думаю, что следует придерживаться одного подхода к именованию.
3) Есть такое правило, что если класс помимо конструктора содержит всего один метод, то стоит задуматься, а нужен ли вообще такой класс. Возможно стоит конвертировать его в просто в метод, чтобы не слишком усложнять код и не плодить сущности.
Про то, что плохая практика в конструкторе класса делать "тяжелые" операции, не связанные с инициализацией объекта уже написали.
4) Я бы предложил использовать автоматическое выведение типов (var) в конструкциях, вроде:
JsonWriter<Person> jsonWriter = new JsonWriter<Person>();
JsonReader<Person> jsonReader = new JsonReader<Person>();
Заменил бы на
var jsonWriter = new JsonWriter<Person>();
var jsonReader = new JsonReader<Person>();
Это лучше читается, для такого "масла масленного" этот сахар и был придуман.
5) Вызов метода Dispose() у класса PersonsGenerator.
Класс PersonsGenerator судя по коду из статьи не реализует ни интерфейс IDisposable, ни собственно метод Dispose(). Скорее всего это опечатка, иначе этот код просто бы не работал.
Не понятно, что вообще должен в данном случае делать этот метод, так как очистка PersonsGenerator.persons производится явно, вне данного метода. Вероятно, эту операцию как раз надо засунуть внутрь Dispose(). И тогда использовать генератор вместе с конструкцией using:
using (var personsGenerator = new PersonsGenerator()) { ... }
Но я бы вообще не стал хранить в генераторе сгенерированные данные. Ответственность генератора - генерировать сущености, а не хранить их.
6) Не стоит сохранять в финальном коде отладочные куски, я про это:
// Не обращаем внимание, так, для себя сделал
7) В дополнение к 6), для вывода небольших массивов в отладочной строке можно было бы воспользоваться методом string.Join(), тогда можно было бы элементы массивов выводить через разделитель, например через запятую.
Вообще мне кажется, что тут рефлексия не особенно нужна, можно было бы для класса Person переопределить метод ToString() и в явном виде форматировать данные. Или вообще для отладочного вывода просто печатать готовый json в котором уже произведена почти аналогичная сериализация данных, так сказать бесплатно и без лишнего кода.
8) Мне понравилась обертка для Faker, которая называется Bogus (https://github.com/bchavez/Bogus). Рекомендую посмотреть на ее реализацию создания декларативных генераторов, мне кажется, что это довольно красивое решение, которое иногда избавляет от необходимости написания своих классов-генераторов. Плюс эта библиотека содержит кучу дополнительных расширений, среди которых, например есть возможность генерировать данные для не-англоязычных сред, например имена на русском языке.
Все вышесказанное - мое имхо и не является истиной в последней инстанции, надеюсь какие-то из советов будут полезными, желаю удачи автору статьи с поиском работы!
Примерный вид аналогичного кода на Processing:
Так в том и засада, что 8 в UTF-8, 16 в UTF-16, означает минимальную длину в битах, которую может использовать кодировка, но при этом ни как не говорит о максимальной длине. Отсюда и лезут ноги у забулждения, что UTF-8 использует один, а UTF-16 два, написано же 8 и 16 бит, а факт того, что вся кодовая таблица UNICODE при всем желании ни в один ни в два байта не влезет во внимание не берется.
Кстати, здесь же в статье есть еще неточность:
Современные операционные системы, как правило, используют UTF-8
Если я правильно понимаю, то Windows вообще по-умолчанию использует Windows-1252 или Windows-1251 (либо другую "локальную" кодировку), а в случае юникода раньше использовалась одна из UTF-16 (little endian / big endian). Поддержка UTF-8, в качестве кодировки по-умолчанию, появилась сравнительно недавно. Но я могу заблуждаться, подробно в этой теме не разбирался.
Спасибо за уточнение, про "от одного байта" - опечатка, конечно от двух. А вот про два либо четыре вылетело из головы.
Это - заблуждение. UTF-8 использует переменное количество байт, от одного до четырёх. Один байт используется в случае кодировки символов из таблицы ASCII. UTF-16, точно так же использует от 1 до 4 байт в зависимости от кодируемого символа.
Рубрика «Вредные советы». Если вдруг Вам по какой-либо причине захочется воспользоваться оператором * для создания итерируемого объекта другого типа на основе существующего, то нужно просто воспользоваться конструктором нужного типа:
Вместо какой-то нечитаемой конструкции, проблему которой сам же автор признает:
Конечно же не понятно, что сделать-то хотели? Конвертировать строку в список? Ну так и пишите! Вместо list может быть tuple, deque, set или другие коллекции, поддерживающие инициализацию из итерируемого объекта.