День девятьсот девяносто пятый. #ЗаметкиНаПолях
Сравнение Строк Сложнее, Чем Кажется. Продолжение
Начало
NLS и ICU
В прошлом API глобализации .NET использовали разные базовые библиотеки на разных платформах. В Unix использовались международные компоненты для Unicode (ICU), а в Windows использовалась поддержка национальных языков (NLS). Это привело к некоторым различиям в поведении нескольких API глобализации при запуске приложений на разных платформах. В .NET 5.0 поведение среды выполнения изменилось. API глобализации теперь по умолчанию используют ICU на всех поддерживаемых платформах. Это позволяет приложениям избегать различий между платформами.
Обратите внимание, что ICU также используется в Windows. DLL-библиотеки ICU поставляются с Windows, начиная с Windows 10 версии 1703. Многие приложения уже начали использовать ICU в Windows. Таким образом, переход на использование ICU происходит повсюду, а не только в .NET.
.NET Framework 1.0-4.8: NLS в Windows
NET Core 1.0-3.1: NLS в Windows, ICU в Linux
.NET 5.0+: ICU* в Windows, ICU в Linux
* Можно принудительно использовать NLS с помощью флага System.Globalization.UseNls в файле конфигурации.
Если в версии Windows нет ICU, она автоматически возвращается к NLS. NLS и ICU в некоторых крайних случаях ведут себя по-разному (см. ниже). Кроме того, новая версия библиотеки может вносить изменения в поведение.
Обратите внимание, что переход с NLS на ICU не является критическим изменением. Изменения данных глобализации происходят даже в NLS, и поведение API не следует считать стабильным.
У методов разные режимы сравнения по умолчанию
Вы всегда должны явно указывать компаратор, поскольку значения по умолчанию в разных методах не согласованы. Например,
Анализаторы кода могут обнаруживать места потенциальных ошибок. Чтобы защититься от неожиданного поведения, рекомендуется включить в проекте анализаторы кода Roslyn. Они помогут пометить код, который может непреднамеренно использовать лингвистический компаратор, когда вероятнее всего подразумевался порядковый компаратор. Следующие правила должны помочь выявить эти проблемы:
- CA1307: Specify StringComparison for clarity (для ясности укажите StringComparison)
- CA1309: Use ordinal StringComparison (используйте порядковый режим сравнения)
- CA1310: Specify StringComparison for correctness (укажите StringComparison для корректности)
Эти особые правила не включены по умолчанию. Чтобы включить их и отображать любые нарушения как ошибки сборки, установите следующие свойства в файле проекта:
- https://www.meziantou.net/string-comparisons-are-harder-than-it-seems.htm
- https://docs.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus
Сравнение Строк Сложнее, Чем Кажется. Продолжение
Начало
NLS и ICU
В прошлом API глобализации .NET использовали разные базовые библиотеки на разных платформах. В Unix использовались международные компоненты для Unicode (ICU), а в Windows использовалась поддержка национальных языков (NLS). Это привело к некоторым различиям в поведении нескольких API глобализации при запуске приложений на разных платформах. В .NET 5.0 поведение среды выполнения изменилось. API глобализации теперь по умолчанию используют ICU на всех поддерживаемых платформах. Это позволяет приложениям избегать различий между платформами.
Обратите внимание, что ICU также используется в Windows. DLL-библиотеки ICU поставляются с Windows, начиная с Windows 10 версии 1703. Многие приложения уже начали использовать ICU в Windows. Таким образом, переход на использование ICU происходит повсюду, а не только в .NET.
.NET Framework 1.0-4.8: NLS в Windows
NET Core 1.0-3.1: NLS в Windows, ICU в Linux
.NET 5.0+: ICU* в Windows, ICU в Linux
* Можно принудительно использовать NLS с помощью флага System.Globalization.UseNls в файле конфигурации.
Если в версии Windows нет ICU, она автоматически возвращается к NLS. NLS и ICU в некоторых крайних случаях ведут себя по-разному (см. ниже). Кроме того, новая версия библиотеки может вносить изменения в поведение.
Обратите внимание, что переход с NLS на ICU не является критическим изменением. Изменения данных глобализации происходят даже в NLS, и поведение API не следует считать стабильным.
У методов разные режимы сравнения по умолчанию
Вы всегда должны явно указывать компаратор, поскольку значения по умолчанию в разных методах не согласованы. Например,
string.IndexOf
использует текущий язык и региональные параметры, тогда как string.Equals
использует Ordinal
. Поэтому всегда используйте перегрузку метода с StringComparison
, IEqualityComparer<string>
или IComparer<string>
, когда это возможно:// true, т.к. используется режим сравнения Ordinal
"A\r\nB".Contains("\n");
IndexOf
по причинам, описанным выше, в .NET 5+ выдаёт -1, т.к. используется текущая культура, а до .NET 5 в результате будет 2:"A\r\nB".IndexOf("\n");Это также относится к
Equals
и CompareTo
(и всем операторам ==
, <
, >
, и т.п.):// falseA
"encyclopædia".Equals("encyclopaedia");
CompareTo
опять же выдаёт 0 (равны) до .NET 5 и 1 в .NET 5+:"encyclopædia".CompareTo("encyclopaedia");Защита от неожиданного поведения
Анализаторы кода могут обнаруживать места потенциальных ошибок. Чтобы защититься от неожиданного поведения, рекомендуется включить в проекте анализаторы кода Roslyn. Они помогут пометить код, который может непреднамеренно использовать лингвистический компаратор, когда вероятнее всего подразумевался порядковый компаратор. Следующие правила должны помочь выявить эти проблемы:
- CA1307: Specify StringComparison for clarity (для ясности укажите StringComparison)
- CA1309: Use ordinal StringComparison (используйте порядковый режим сравнения)
- CA1310: Specify StringComparison for correctness (укажите StringComparison для корректности)
Эти особые правила не включены по умолчанию. Чтобы включить их и отображать любые нарушения как ошибки сборки, установите следующие свойства в файле проекта:
<PropertyGroup>Источники:
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<WarningsAsErrors>
$(WarningsAsErrors);CA1307;CA1309;CA1310
</WarningsAsErrors>
</PropertyGroup>
- https://www.meziantou.net/string-comparisons-are-harder-than-it-seems.htm
- https://docs.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus
День девятьсот девяносто шестой. #Оффтоп
Противоречивые Мнения Разработчиков ПО
Отличной пятницы вам, господа. И у меня для вас сегодня вот такая тема для обсуждения. Периодически мы сталкиваемся с такими рассуждениями из уст даже уважаемых в сообществе людей. Приведу несколько примеров из видео по ссылке ниже (кроме тех, которые на канале и так широко обсуждались), а в комментариях расскажите, с чем согласны, с чем нет. И предлагайте свои варианты, от которых у вас «пригорает» больше всего.
1. Программисты, которые не пишут код в свободное время для развлечения, никогда не станут такими же хорошими, как те, кто это делает
Даже самые умные и талантливые люди никогда не станут по-настоящему хорошими программистами, если они не будут относиться к этому как к чему-то большему, чем работа. То есть они они делают небольшие проекты на стороне или просто возятся с множеством разных языков и идей в свободное время. Это не значит, что хорошие программисты ничего не делают, кроме программирования, но они делают больше, чем просто пишут код с 9 до 5.
2. Ленивые программисты - лучшие программисты
Ленивый программист чаще находит способы сократить время, затрачиваемое на написание кода. Это в итоге превращается в инструменты и рабочие процессы, которые могут принести пользу другим разработчикам в компании/команде. Такие разработчики могут искать утилиты или писать мелкие скрипты для автоматизации часто выполняемых действий. Ленивому программисту может потребоваться несколько дополнительных часов, чтобы выпустить первую версию продукта, но он сэкономит месяцы в будущем.
3. ИТ специальность делает вас более разносторонним программистом
Формальное образование открывает вам другие возможности мышления и даёт отличный базис. То, что вы написали код лучше, чем бакалавр в ИТ, не значит, что вы лучше него. Он сможет легко наверстать упущенное, а вот наоборот – вряд ли. Наличие квалификации также показывает целеустремлённость, настойчивость и тот факт, что человек сделает всё возможное, чтобы стать лучше.
4. Тесты не нужно писать заранее, а иногда и вовсе не нужно
Разработчики плохо тестируют собственный код. Вот почему обычно есть группы QA. В большинстве случаев код, который мы пишем, переплетается с другим кодом, который нужно тестировать отдельно, поэтому мы в итоге обмазываемся паттернами, чтобы обеспечить тестируемость. Не то чтобы паттерны – это плохо, но иногда они могут добавлять ненужной сложности, и все ради тестирования… что часто всё равно не работает. Чтобы написать исчерпывающий тест, требуется много времени. Часто больше времени, чем мы готовы выделить. И чем более комплексным является тест, тем более хрупким он становится. Если интерфейс объекта, который он тестирует, изменяется, мы вынуждены переписать тест, который больше не срабатывает. А если меняются требования к системе…
5. Клиент не всегда прав
Слишком часто разработчики просто пишут код, который их просят, и не пытаются разобраться в продукте. Роль разработчика в том, чтобы помогать бизнесу выражать свои идеи. При этом разработчик должен быть заинтересован в понимании бизнеса, чтобы он мог предоставить наилучший возможный результат. И это подразумевает, что иногда владелец продукта будет просить сделать «революционную новинку», а разработчику придётся либо согласиться с этим фактом, либо объяснять наиболее вероятную причину, почему это невозможно. Это взаимовыгодно, потому что владелец продукта понимает, как его мысли воплощаются в продукте, а команда разработчиков понимает, что они делают нечто большее, чем просто пишут код.
6. Не страшно чего-то не знать. Но тебя уволят, если ты даже не сможешь это нагуглить
Интернет (и гугл в частности) - это инструмент. И эффективное его использование – это один из важных навыков, которым должен обладать разработчик.
Источник: https://youtu.be/goy4lZfDtCE
Противоречивые Мнения Разработчиков ПО
Отличной пятницы вам, господа. И у меня для вас сегодня вот такая тема для обсуждения. Периодически мы сталкиваемся с такими рассуждениями из уст даже уважаемых в сообществе людей. Приведу несколько примеров из видео по ссылке ниже (кроме тех, которые на канале и так широко обсуждались), а в комментариях расскажите, с чем согласны, с чем нет. И предлагайте свои варианты, от которых у вас «пригорает» больше всего.
1. Программисты, которые не пишут код в свободное время для развлечения, никогда не станут такими же хорошими, как те, кто это делает
Даже самые умные и талантливые люди никогда не станут по-настоящему хорошими программистами, если они не будут относиться к этому как к чему-то большему, чем работа. То есть они они делают небольшие проекты на стороне или просто возятся с множеством разных языков и идей в свободное время. Это не значит, что хорошие программисты ничего не делают, кроме программирования, но они делают больше, чем просто пишут код с 9 до 5.
2. Ленивые программисты - лучшие программисты
Ленивый программист чаще находит способы сократить время, затрачиваемое на написание кода. Это в итоге превращается в инструменты и рабочие процессы, которые могут принести пользу другим разработчикам в компании/команде. Такие разработчики могут искать утилиты или писать мелкие скрипты для автоматизации часто выполняемых действий. Ленивому программисту может потребоваться несколько дополнительных часов, чтобы выпустить первую версию продукта, но он сэкономит месяцы в будущем.
3. ИТ специальность делает вас более разносторонним программистом
Формальное образование открывает вам другие возможности мышления и даёт отличный базис. То, что вы написали код лучше, чем бакалавр в ИТ, не значит, что вы лучше него. Он сможет легко наверстать упущенное, а вот наоборот – вряд ли. Наличие квалификации также показывает целеустремлённость, настойчивость и тот факт, что человек сделает всё возможное, чтобы стать лучше.
4. Тесты не нужно писать заранее, а иногда и вовсе не нужно
Разработчики плохо тестируют собственный код. Вот почему обычно есть группы QA. В большинстве случаев код, который мы пишем, переплетается с другим кодом, который нужно тестировать отдельно, поэтому мы в итоге обмазываемся паттернами, чтобы обеспечить тестируемость. Не то чтобы паттерны – это плохо, но иногда они могут добавлять ненужной сложности, и все ради тестирования… что часто всё равно не работает. Чтобы написать исчерпывающий тест, требуется много времени. Часто больше времени, чем мы готовы выделить. И чем более комплексным является тест, тем более хрупким он становится. Если интерфейс объекта, который он тестирует, изменяется, мы вынуждены переписать тест, который больше не срабатывает. А если меняются требования к системе…
5. Клиент не всегда прав
Слишком часто разработчики просто пишут код, который их просят, и не пытаются разобраться в продукте. Роль разработчика в том, чтобы помогать бизнесу выражать свои идеи. При этом разработчик должен быть заинтересован в понимании бизнеса, чтобы он мог предоставить наилучший возможный результат. И это подразумевает, что иногда владелец продукта будет просить сделать «революционную новинку», а разработчику придётся либо согласиться с этим фактом, либо объяснять наиболее вероятную причину, почему это невозможно. Это взаимовыгодно, потому что владелец продукта понимает, как его мысли воплощаются в продукте, а команда разработчиков понимает, что они делают нечто большее, чем просто пишут код.
6. Не страшно чего-то не знать. Но тебя уволят, если ты даже не сможешь это нагуглить
Интернет (и гугл в частности) - это инструмент. И эффективное его использование – это один из важных навыков, которым должен обладать разработчик.
Источник: https://youtu.be/goy4lZfDtCE
👍1
День девятьсот девяносто седьмой. #ПолезныйКод
Загрузка сертификата SSL/TLS в .NET
Недавно мне потребовалось настроить оповещение, когда срок действия сертификата подходит к концу или когда он использует небезопасный алгоритм подписи. Первый шаг - получить сертификат. В .NET для этого вы можете использовать класс
Источник: https://www.meziantou.net/downloading-a-ssl-certificate-in-dotnet.htm
Загрузка сертификата SSL/TLS в .NET
Недавно мне потребовалось настроить оповещение, когда срок действия сертификата подходит к концу или когда он использует небезопасный алгоритм подписи. Первый шаг - получить сертификат. В .NET для этого вы можете использовать класс
SslStream
.static class CertificateDownloaderИспользование:
{
//Этот метод обратного вызова нужен для проверки безопасности сертификата
//Но здесь нам не нужна проверка, мы только получаем данные сертификата
private static readonly
RemoteCertificateValidationCallback
сallback = (_, _, _, _) => true;
public static async Task<X509Certificate2?>
GetCertificateAsync(string domain, int port = 443)
{
using var client = new TcpClient(domain, port);
using var sslStream =
new SslStream(client.GetStream(), true, сallback);
// Инициируем соединение, чтобы скачать сертификат
await sslStream
.AuthenticateAsClientAsync(domain)
.ConfigureAwait(false);
var cert = sslStream.RemoteCertificate;
if (cert != null)
return new X509Certificate2(cert);
return null;
}
}
static async Task Main()Далее можно настроить повторяющуюся задачу в Azure Pipelines или GitHub Actions для ежедневной проверки сертификатов, но это выходит за рамки этого поста.
{
var cert = await
CertificateDownloader.GetCertificateAsync("www.google.com");
Console.WriteLine($"Subject: {cert?.Subject}");
Console.WriteLine($"Issuer: {cert?.Issuer}");
Console.WriteLine($"NotBefore: {cert?.NotBefore}");
Console.WriteLine($"NotAfter: {cert?.NotAfter}");
Console.WriteLine($"Algorithm: {cert?.SignatureAlgorithm.FriendlyName}");
}
Источник: https://www.meziantou.net/downloading-a-ssl-certificate-in-dotnet.htm
День девятьсот девяносто восьмой. #ЗаметкиНаПолях #AsyncTips
Обработка задач при завершении
Задача
Имеется коллекция задач, которые будут использоваться с await; требуется организовать обработку каждой задачи после ее завершения. При этом обработка каждой задачи должна происходить сразу же после завершения, без ожидания других задач.
Допустим, у нас есть некоторый набор однотипных задач. Для простоты возьмём задачу, которая просто ожидает заданное количество секунд:
Решение заключается в добавлении оборачивающего асинхронного метода, который обеспечивает ожидание задачи и обработку ее результата. Этот метод можно записать как асинхронную лямбду:
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
Обработка задач при завершении
Задача
Имеется коллекция задач, которые будут использоваться с await; требуется организовать обработку каждой задачи после ее завершения. При этом обработка каждой задачи должна происходить сразу же после завершения, без ожидания других задач.
Допустим, у нас есть некоторый набор однотипных задач. Для простоты возьмём задачу, которая просто ожидает заданное количество секунд:
async Task<int> DelayAndReturnAsync(int value)Создадим коллекцию этих задач:
{
await Task.Delay(TimeSpan.FromSeconds(value));
return value;
}
Task<int> taskA = DelayAndReturnAsync(2);Можно ожидать каждую задачу в цикле, но тогда они будут обрабатываться последовательно в порядке их нахождения в коллекции:
Task<int> taskB = DelayAndReturnAsync(3);
Task<int> taskC = DelayAndReturnAsync(1);
Task<int>[] tasks = new[] { taskA, taskB, taskC };
// Выводит "2", "3" и "1" вместо "1", "2" и "3".Решение
async Task ProcessTasksAsync(Task<int>[] tasks)
{
foreach (Task<int> task in tasks)
{
var result = await task;
Trace.WriteLine(result);
}
}
Решение заключается в добавлении оборачивающего асинхронного метода, который обеспечивает ожидание задачи и обработку ее результата. Этот метод можно записать как асинхронную лямбду:
async Task ProcessTasksAsync(Task<int>[] tasks)В этом решении обработка задач выполняется конкурентно, тогда как в исходном коде задачи обрабатывались по очереди. Обычно это не создаёт затруднений, но, если такой способ обработки в вашей ситуации недопустим, рассмотрите возможность использования блокировок.
{
Task[] processing = tasks.Select(async t =>
{
var result = await t;
Trace.WriteLine(result);
}).ToArray();
// Ожидаем завершения всей обработки
await Task.WhenAll(processing);
}
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
День девятьсот девяносто девятый. #ЧтоНовенького
Hot Reload Убрали Отовсюду, Кроме Visual Studio 2022… Но Потом Вернули
Суть
В прошлую среду Microsoft объявили о последних подготовках к выходу .NET 6 (кстати, презентация пройдёт на .NET Conf 2021, начало 9 ноября в 19:00 по Москве). Отдельным большим постом было объявление о релизе Hot Reload, из которого стало известно, что широко разрекламированную утилиту внезапно решили выпилить отовсюду, кроме Visual Studio 2022. То есть, она не работала бы ни в VS Code, ни в Rider, ни в консольных утилитах вроде
Развитие драмы
Решение было быстро замечено и раскритиковано чуть менее, чем всем .NET сообществом. Вот например тред от Microsoft MVP Шона Киллина. Основной посыл критиков в том, что такое решение подрывает доверие ко всей экосистеме. Более того, этот поступок был практически бессмысленным, т.к. весь код утилиты был открыт, и ничто не мешало энтузиастам взять его и запилить собственные версии. А JetBrains уже в пятницу объявили об обновлении Rider, поддерживающем Hot Reload.
В результате в субботу в Microsoft, что называется, «дали заднюю». Директор по управлению программами .NET Скотт Хантер принёс извинения сообществу и сообщил, что пулл реквест по возвращению Hot Reload в .NET SDK будет удовлетворён.
Что это было?
Да чёрт его знает. Мотивы поступка менеджеров Microsoft до сих пор не ясны. Стимулировать использование новой VS 2022? По слухам Microsoft особой прибыли от IDE не получают. Основной поток идёт от Azure. Да и вряд ли это стало бы решающим фактором при выборе рабочего процесса.
В общем очередная победа гражданского общества над корпорацией зла… Хотя, может на это и был изначальный расчёт – нагнать хайпа перед релизом .NET 6?
Источник: https://devblogs.microsoft.com/dotnet/net-hot-reload-support-via-cli/
Hot Reload Убрали Отовсюду, Кроме Visual Studio 2022… Но Потом Вернули
It’s been 0 days since .NET had drama.Такое сообщение выдаёт недавно созданная шуточная утилита dotnet-drama, которую успели написать за выходные.
Суть
В прошлую среду Microsoft объявили о последних подготовках к выходу .NET 6 (кстати, презентация пройдёт на .NET Conf 2021, начало 9 ноября в 19:00 по Москве). Отдельным большим постом было объявление о релизе Hot Reload, из которого стало известно, что широко разрекламированную утилиту внезапно решили выпилить отовсюду, кроме Visual Studio 2022. То есть, она не работала бы ни в VS Code, ни в Rider, ни в консольных утилитах вроде
dotnet watch
. Причём, поначалу было не ясно, почему было принято такое решение. Но, судя по объяснениям от Microsoft (а точнее по их отсутствию), скоро стало понятно, что решение было не техническим, а чисто менеджерским. То есть, готовую рабочую утилиту, которой многие уже начали пользоваться даже в режиме превью, решили убрать… «просто потому что».Развитие драмы
Решение было быстро замечено и раскритиковано чуть менее, чем всем .NET сообществом. Вот например тред от Microsoft MVP Шона Киллина. Основной посыл критиков в том, что такое решение подрывает доверие ко всей экосистеме. Более того, этот поступок был практически бессмысленным, т.к. весь код утилиты был открыт, и ничто не мешало энтузиастам взять его и запилить собственные версии. А JetBrains уже в пятницу объявили об обновлении Rider, поддерживающем Hot Reload.
В результате в субботу в Microsoft, что называется, «дали заднюю». Директор по управлению программами .NET Скотт Хантер принёс извинения сообществу и сообщил, что пулл реквест по возвращению Hot Reload в .NET SDK будет удовлетворён.
Что это было?
Да чёрт его знает. Мотивы поступка менеджеров Microsoft до сих пор не ясны. Стимулировать использование новой VS 2022? По слухам Microsoft особой прибыли от IDE не получают. Основной поток идёт от Azure. Да и вряд ли это стало бы решающим фактором при выборе рабочего процесса.
В общем очередная победа гражданского общества над корпорацией зла… Хотя, может на это и был изначальный расчёт – нагнать хайпа перед релизом .NET 6?
Источник: https://devblogs.microsoft.com/dotnet/net-hot-reload-support-via-cli/
День 1000.
И вот так незаметно прошла 1000 дней. Кстати, мне порядком надоело писать числа прописью, тем более что теперь это будет совсем длинно. Поэтому дальше будут цифры.
К юбилею вот подогнали книжку, над переводом которой работал, поэтому вот хвастаюсь. Купить можно тут.
Спасибо, что читаете. Отдельное спасибо за комментарии и обсуждения в чате.
Может, пора уже какой-нибудь мерч выпустить, что скажете? Давайте для пробы начнём с кружек. Напишите в комментариях, кто хочет кружку. Среди желающих выберу случайным образом несколько человек и отправлю им сувениры. Только сразу оговорюсь, будьте готовы сообщить мне реальные ФИО и адреса, куда прислать.
И вот так незаметно прошла 1000 дней. Кстати, мне порядком надоело писать числа прописью, тем более что теперь это будет совсем длинно. Поэтому дальше будут цифры.
К юбилею вот подогнали книжку, над переводом которой работал, поэтому вот хвастаюсь. Купить можно тут.
Спасибо, что читаете. Отдельное спасибо за комментарии и обсуждения в чате.
Может, пора уже какой-нибудь мерч выпустить, что скажете? Давайте для пробы начнём с кружек. Напишите в комментариях, кто хочет кружку. Среди желающих выберу случайным образом несколько человек и отправлю им сувениры. Только сразу оговорюсь, будьте готовы сообщить мне реальные ФИО и адреса, куда прислать.
День 1002. #ProjectManagement
Почему Плохое ПО Случается с Хорошими Людьми. Начало
Плохое ПО - одна из немногих вещей, которую нельзя решить с помощью денег. У огромных авиакомпаний приложения для поиска рейсов часто уступают студенческим проектам. Корпоративные ИТ-системы - это монстры с огромными бюджетами, создаваемые в течение многих лет. Как бы то ни было, причина плохого ПО не в недостатке финансирования.
Удивительно, но основная причина плохого ПО связана с тем, как управляются проекты разработки. Худшие программные проекты часто создаются схожим образом.
Владельцы проекта хотят создать конкретное решение, никогда явно не определяя проблему, которую они пытаются решить. Они собирают длинный список требований от большой группы заинтересованных сторон. Список передаётся большой группе внешних разработчиков, которая создаёт требуемое ПО с нуля. Когда все требования выполнены, все празднуют окончание проекта.
Однако, проблемы обнаруживаются, когда система попадает в руки реальных пользователей. Она медленная, запутанная и наполнена трудноуловимыми ошибками, из-за которых её использование становится неудобным. К сожалению, к этому времени внешняя группа разработчиков распущена, и некому вносить необходимые исправления. А люди, поддерживающие систему, зачастую не знают, что вызвало эти проблемы изначально, поэтому не могут их эффективно решить, и всё можно начинать заново.
Есть особенности ПО, которые позволяют добиваться успеха даже с ограниченным бюджетом:
1. Повторное использование хорошего ПО позволяет быстро создавать хорошие вещи.
2. Полезность ПО ограничивается не количеством ресурсов, вложенных в его создание, а тем, насколько сложным оно может стать до того, как сломается.
3. Основная ценность ПО - это не написанный код, а знания, накопленные людьми, которые его создали.
1. Повторное использование ПО
ПО легко копировать как на уровне кода, так и на уровне модулей. Современное ПО почти никогда не создается с нуля. Даже самые инновационные приложения создаются с использованием существующего ПО, которое было объединено и модифицировано для достижения нового результата.
Самый большой источник повторно используемых модулей кода - это сообщество с открытым исходным кодом. Использование открытого исходного кода не только ускоряет разработку приложений, но и дает вам доступ к технологиям, которые намного сложнее, чем всё, что вы могли бы разработать самостоятельно. Наиболее популярный открытый код также более безопасен, поскольку множество людей находят и исправляют уязвимости.
Появление облачных сервисов ещё больше расширило возможности повторного использования. Сайты, сетевые сервисы, виртуальные машины, базы данных – всё это можно легко получить всего лишь за абонентскую плату. Облачные сервисы позволяют разработчикам получать выгоду от специализации: поставщик услуг занимается настройкой, обслуживанием и непрерывной разработкой надежного высококачественного ПО, которое используется всеми его подписчиками. Это позволяет разработчикам перестать тратить время на решенные проблемы и вместо этого сосредоточиться на предоставлении реальной ценности для своей компании.
Вы не сможете добиться технического прогресса, если всё своё время будете тратить на воссоздание существующих технологий. Программная инженерия - это создание автоматизированных систем, и одна из первых вещей, которые автоматизируются, - это рутинная работа. Суть в том, чтобы понять, какие системы следует использовать повторно, как настроить их в соответствии с вашими уникальными требованиями и устранить проблемы, обнаруженные в процессе настройки.
Окончание следует...
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
Почему Плохое ПО Случается с Хорошими Людьми. Начало
Плохое ПО - одна из немногих вещей, которую нельзя решить с помощью денег. У огромных авиакомпаний приложения для поиска рейсов часто уступают студенческим проектам. Корпоративные ИТ-системы - это монстры с огромными бюджетами, создаваемые в течение многих лет. Как бы то ни было, причина плохого ПО не в недостатке финансирования.
Удивительно, но основная причина плохого ПО связана с тем, как управляются проекты разработки. Худшие программные проекты часто создаются схожим образом.
Владельцы проекта хотят создать конкретное решение, никогда явно не определяя проблему, которую они пытаются решить. Они собирают длинный список требований от большой группы заинтересованных сторон. Список передаётся большой группе внешних разработчиков, которая создаёт требуемое ПО с нуля. Когда все требования выполнены, все празднуют окончание проекта.
Однако, проблемы обнаруживаются, когда система попадает в руки реальных пользователей. Она медленная, запутанная и наполнена трудноуловимыми ошибками, из-за которых её использование становится неудобным. К сожалению, к этому времени внешняя группа разработчиков распущена, и некому вносить необходимые исправления. А люди, поддерживающие систему, зачастую не знают, что вызвало эти проблемы изначально, поэтому не могут их эффективно решить, и всё можно начинать заново.
Есть особенности ПО, которые позволяют добиваться успеха даже с ограниченным бюджетом:
1. Повторное использование хорошего ПО позволяет быстро создавать хорошие вещи.
2. Полезность ПО ограничивается не количеством ресурсов, вложенных в его создание, а тем, насколько сложным оно может стать до того, как сломается.
3. Основная ценность ПО - это не написанный код, а знания, накопленные людьми, которые его создали.
1. Повторное использование ПО
ПО легко копировать как на уровне кода, так и на уровне модулей. Современное ПО почти никогда не создается с нуля. Даже самые инновационные приложения создаются с использованием существующего ПО, которое было объединено и модифицировано для достижения нового результата.
Самый большой источник повторно используемых модулей кода - это сообщество с открытым исходным кодом. Использование открытого исходного кода не только ускоряет разработку приложений, но и дает вам доступ к технологиям, которые намного сложнее, чем всё, что вы могли бы разработать самостоятельно. Наиболее популярный открытый код также более безопасен, поскольку множество людей находят и исправляют уязвимости.
Появление облачных сервисов ещё больше расширило возможности повторного использования. Сайты, сетевые сервисы, виртуальные машины, базы данных – всё это можно легко получить всего лишь за абонентскую плату. Облачные сервисы позволяют разработчикам получать выгоду от специализации: поставщик услуг занимается настройкой, обслуживанием и непрерывной разработкой надежного высококачественного ПО, которое используется всеми его подписчиками. Это позволяет разработчикам перестать тратить время на решенные проблемы и вместо этого сосредоточиться на предоставлении реальной ценности для своей компании.
Вы не сможете добиться технического прогресса, если всё своё время будете тратить на воссоздание существующих технологий. Программная инженерия - это создание автоматизированных систем, и одна из первых вещей, которые автоматизируются, - это рутинная работа. Суть в том, чтобы понять, какие системы следует использовать повторно, как настроить их в соответствии с вашими уникальными требованиями и устранить проблемы, обнаруженные в процессе настройки.
Окончание следует...
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
День 1003. #ProjectManagement
Почему Плохое ПО Случается с Хорошими Людьми. Окончание
Начало
2. ПО ограничено сложностью
Полезность ПО обычно ограничивается его сложностью, а не объемом ресурсов, вложенных в его создание.
ИТ-системы часто полны функций, но пользователи по-прежнему ненавидят их из-за того, насколько запутанными они становятся. Напротив, лучшие мобильные приложения, как правило, хвалят за простоту и интуитивность. Научиться пользоваться программой сложно. А новые функции только ухудшают положение пользователей - сказывается накопленная сложность. Для пользователя удобство не в том, сколько функций может быть реализовано в программе, а в том, что может поместиться в простой интуитивно понятный интерфейс.
Но и инженерный прогресс замедляется, когда проект становится слишком сложным. Каждая новая строка кода, добавляемая в приложение, может взаимодействовать с любой другой строкой. Чем больше кодовая база, тем больше ошибок появляется при создании новой функции. В конце концов, объём работы по внедрению новой функции нивелируется объёмом работы по исправлению ошибок. Это известно как «технический долг» и является основной проблемой при разработке профессионального ПО. По этой причине во многих крупных ИТ-системах есть проблемы, которые не решаются годами.
В таких случаях единственный путь вперед - сделать шаг назад: рационализировать и упростить кодовую базу. Изменить архитектуру, чтобы ограничить неожиданные взаимодействия, удалить некритические функции, использовать автоматизированные инструменты для проверки ошибок.
Создание хорошего ПО предполагает чередование циклов расширения и уменьшения сложности. По мере появления новых функций в системе естественным образом накапливается беспорядок. Когда этот беспорядок начинает вызывать проблемы, прогресс приостанавливается, чтобы дать время на очистку. Этот двухэтапный процесс необходим, потому что идеально хорошей инженерии не существует. Задача состоит в том, чтобы управлять этим циклом, позволяя ПО стать достаточно беспорядочным, чтобы добиться значимого прогресса, но не позволяя ему становиться настолько сложным, что с ним невозможно справиться.
3. ПО - это не только написание кода, но и накопление знаний.
В разработке ПО большинство идей плохие. Их количество настолько велико, что любая конкретная идея, вероятно, не сработает, даже если она была тщательно продумана и отобрана. Чтобы добиться прогресса, нужно начать с множества плохих идей, отбросить худшие и развить самые многообещающие. Конечный продукт может быть обманчиво простым, но знание того, почему было выбрано именно это решение, позволяет ему быть хорошим.
Эти знания остаются важными даже после создания продукта. Если новая команда возьмёт на себя код незнакомого ПО, оно вскоре начнёт деградировать. Появятся новые требования, обнаружатся ошибки в безопасности, и все эти проблемы новая команда, не имея глубоких знаний архитектуры системы и принципов проектирования, скорее всего будет решать временными заплатками. Из-за этого появятся новые ошибки, а сложность системы в целом возрастёт. К ПО следует относиться не как к статичному продукту, а как к живому проявлению коллективного понимания проблемы командой разработчиков.
Вот почему сложно полагаться на аутсорс при разработке ключевого для компании ПО. Вы можете получить работающую систему и её код, но бесценные знания о том, как она построена и какие варианты дизайна были выбраны, покинут организацию. Поэтому передача системы новым людям для «обслуживания» часто вызывает проблемы. Даже если система очень хорошо документирована, некоторые знания теряются каждый раз, когда приходит новая команда. С годами система превращается в лоскутное одеяло из кода разных авторов. В конце концов, не остаётся никого, кто действительно понимал бы, как всё это работает. Чтобы ПО продолжало хорошо работать в долгосрочной перспективе, обслуживающий персонал должен работать и учиться вместе с аутсорс командой, чтобы сохранить важные инженерные знания внутри вашей организации.
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
Почему Плохое ПО Случается с Хорошими Людьми. Окончание
Начало
2. ПО ограничено сложностью
Полезность ПО обычно ограничивается его сложностью, а не объемом ресурсов, вложенных в его создание.
ИТ-системы часто полны функций, но пользователи по-прежнему ненавидят их из-за того, насколько запутанными они становятся. Напротив, лучшие мобильные приложения, как правило, хвалят за простоту и интуитивность. Научиться пользоваться программой сложно. А новые функции только ухудшают положение пользователей - сказывается накопленная сложность. Для пользователя удобство не в том, сколько функций может быть реализовано в программе, а в том, что может поместиться в простой интуитивно понятный интерфейс.
Но и инженерный прогресс замедляется, когда проект становится слишком сложным. Каждая новая строка кода, добавляемая в приложение, может взаимодействовать с любой другой строкой. Чем больше кодовая база, тем больше ошибок появляется при создании новой функции. В конце концов, объём работы по внедрению новой функции нивелируется объёмом работы по исправлению ошибок. Это известно как «технический долг» и является основной проблемой при разработке профессионального ПО. По этой причине во многих крупных ИТ-системах есть проблемы, которые не решаются годами.
В таких случаях единственный путь вперед - сделать шаг назад: рационализировать и упростить кодовую базу. Изменить архитектуру, чтобы ограничить неожиданные взаимодействия, удалить некритические функции, использовать автоматизированные инструменты для проверки ошибок.
Создание хорошего ПО предполагает чередование циклов расширения и уменьшения сложности. По мере появления новых функций в системе естественным образом накапливается беспорядок. Когда этот беспорядок начинает вызывать проблемы, прогресс приостанавливается, чтобы дать время на очистку. Этот двухэтапный процесс необходим, потому что идеально хорошей инженерии не существует. Задача состоит в том, чтобы управлять этим циклом, позволяя ПО стать достаточно беспорядочным, чтобы добиться значимого прогресса, но не позволяя ему становиться настолько сложным, что с ним невозможно справиться.
3. ПО - это не только написание кода, но и накопление знаний.
В разработке ПО большинство идей плохие. Их количество настолько велико, что любая конкретная идея, вероятно, не сработает, даже если она была тщательно продумана и отобрана. Чтобы добиться прогресса, нужно начать с множества плохих идей, отбросить худшие и развить самые многообещающие. Конечный продукт может быть обманчиво простым, но знание того, почему было выбрано именно это решение, позволяет ему быть хорошим.
Эти знания остаются важными даже после создания продукта. Если новая команда возьмёт на себя код незнакомого ПО, оно вскоре начнёт деградировать. Появятся новые требования, обнаружатся ошибки в безопасности, и все эти проблемы новая команда, не имея глубоких знаний архитектуры системы и принципов проектирования, скорее всего будет решать временными заплатками. Из-за этого появятся новые ошибки, а сложность системы в целом возрастёт. К ПО следует относиться не как к статичному продукту, а как к живому проявлению коллективного понимания проблемы командой разработчиков.
Вот почему сложно полагаться на аутсорс при разработке ключевого для компании ПО. Вы можете получить работающую систему и её код, но бесценные знания о том, как она построена и какие варианты дизайна были выбраны, покинут организацию. Поэтому передача системы новым людям для «обслуживания» часто вызывает проблемы. Даже если система очень хорошо документирована, некоторые знания теряются каждый раз, когда приходит новая команда. С годами система превращается в лоскутное одеяло из кода разных авторов. В конце концов, не остаётся никого, кто действительно понимал бы, как всё это работает. Чтобы ПО продолжало хорошо работать в долгосрочной перспективе, обслуживающий персонал должен работать и учиться вместе с аутсорс командой, чтобы сохранить важные инженерные знания внутри вашей организации.
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
День 1004. #NetBasics
Чем Отличается SDK от Runtime?
Официальная страница .NET предлагает 2 опции для скачивания:
- SDK (Software Development Kit) – комплект для разработки ПО со средой исполнения,
- Runtime – только среду исполнения.
Среда исполнения — это то, что должно быть установлено на машине конечного пользователя или сервере для запуска приложения .NET. SDK - это набор инструментов для разработки ПО, который позволяет программистам разрабатывать приложения .NET. Проще говоря, SDK — это то, что создаёт исполняемые файлы, а среда исполнения — это то, что может их запускать.
Разработчикам ПО нужно скачивать .NET SDK, чтобы создавать приложения .NET, но веб-сервер или компьютер конечного пользователя могут иметь только среду исполнения .NET, которая гораздо меньше по размеру.
Ещё один момент — это слабая взаимосвязь между разными языками .NET. Как видно на картинке ниже, C#, F# и VB.NET находятся на разных этапах своей жизни и, следовательно, имеют разные версии. Языки могут развиваться независимо и вводить новые языковые функции по своему усмотрению до тех пор, пока связанный компилятор переводит исходный код в действительный IL.
Внимательный наблюдатель мог бы также заметить несоответствие между версией .NET, .NET SDK и среды исполнения .NET. Официальная версия .NET обычно относится к версии среды исполнения .NET, потому что это, по сути, последняя среда исполнения, которую необходимо установить на машине. SDK может иметь другую версию, потому что цепочка инструментов разработки может улучшаться быстрее, чем сама среда исполнения, и поддерживать новые функции и улучшенные процессы разработки, по-прежнему ориентируясь на ту же версию .NET.
Для справки: не для каждого языка программирования требуется SDK и среда исполнения. Например, такие языки, как Rust или Go, которые напрямую компилируются в собственный машинный код, не требуют среды исполнения. Для этих языков доступен только один вариант загрузки, который обычно представляет собой SDK для создания ПО. .NET же похож, например, на Java, в которой также есть JDK (Java Development Kit) для создания программного обеспечения и JRE (Java Runtime Environment) для исполнения кода.
Источник: https://dusted.codes/dotnet-basics
Чем Отличается SDK от Runtime?
Официальная страница .NET предлагает 2 опции для скачивания:
- SDK (Software Development Kit) – комплект для разработки ПО со средой исполнения,
- Runtime – только среду исполнения.
Среда исполнения — это то, что должно быть установлено на машине конечного пользователя или сервере для запуска приложения .NET. SDK - это набор инструментов для разработки ПО, который позволяет программистам разрабатывать приложения .NET. Проще говоря, SDK — это то, что создаёт исполняемые файлы, а среда исполнения — это то, что может их запускать.
Разработчикам ПО нужно скачивать .NET SDK, чтобы создавать приложения .NET, но веб-сервер или компьютер конечного пользователя могут иметь только среду исполнения .NET, которая гораздо меньше по размеру.
Ещё один момент — это слабая взаимосвязь между разными языками .NET. Как видно на картинке ниже, C#, F# и VB.NET находятся на разных этапах своей жизни и, следовательно, имеют разные версии. Языки могут развиваться независимо и вводить новые языковые функции по своему усмотрению до тех пор, пока связанный компилятор переводит исходный код в действительный IL.
Внимательный наблюдатель мог бы также заметить несоответствие между версией .NET, .NET SDK и среды исполнения .NET. Официальная версия .NET обычно относится к версии среды исполнения .NET, потому что это, по сути, последняя среда исполнения, которую необходимо установить на машине. SDK может иметь другую версию, потому что цепочка инструментов разработки может улучшаться быстрее, чем сама среда исполнения, и поддерживать новые функции и улучшенные процессы разработки, по-прежнему ориентируясь на ту же версию .NET.
Для справки: не для каждого языка программирования требуется SDK и среда исполнения. Например, такие языки, как Rust или Go, которые напрямую компилируются в собственный машинный код, не требуют среды исполнения. Для этих языков доступен только один вариант загрузки, который обычно представляет собой SDK для создания ПО. .NET же похож, например, на Java, в которой также есть JDK (Java Development Kit) для создания программного обеспечения и JRE (Java Runtime Environment) для исполнения кода.
Источник: https://dusted.codes/dotnet-basics
1005.png
286.5 KB
День 1005. #NetBasics
Очень понравилась картинка, поэтому решил её перевести. Надеюсь, Кокоса не будет против. Все ссылки на авторство сохранил.
Источник: https://goodies.dotnetos.org/
Очень понравилась картинка, поэтому решил её перевести. Надеюсь, Кокоса не будет против. Все ссылки на авторство сохранил.
Источник: https://goodies.dotnetos.org/
День 1006. #Testing
Видимое и Невидимое в Модульном Тестировании
В экономике существует понятие «видимого и невидимого», что означает, что при реализации какой-либо политики необходимо сосредоточить внимание на обеих его сторонах:
- Желаемые результаты, которые являются видимой частью.
- Непредвиденные последствия - невидимая часть.
У вас всегда будет и то, и другое, независимо от реализуемой политики. Решение о том, применять ли политику, сводится к тщательному взвешиванию потенциальных результатов с потенциальными непредвиденными последствиями - видимыми и невидимыми.
То же самое касается разработки программного обеспечения и, в частности, модульного тестирования. При написании тестов следует учитывать как видимые, так и невидимые части.
Видимая часть — это преимущества, которые предоставляют вам модульные тесты. Невидимая часть — это (часто скрытые) затраты.
Обе части критически важны. Затраты более важны, потому что мы, люди, склонны отдавать предпочтение краткосрочным выгодам и пренебрегать долгосрочными затратами. В экономике существует целая теория, называемая теорией предпочтения времени, которая изучает последствия этой тенденции дисконтировать долгосрочную перспективу в пользу краткосрочной.
Видимая часть модульного тестирования - насколько хорошо ваши тесты защищают вас от ошибок. Невидимая - сколько вам стоит эта защита. Компонент затрат состоит из двух основных подкомпонентов:
- Ремонтопригодность (сколько усилий нужно, чтобы тест оставался работоспособным).
- Устойчивость к рефакторингу (сколько шума генерирует этот тест).
Самым большим препятствием для написания хороших тестов является игнорирование затрат на модульное тестирование. В результате люди, как правило, создают много тестов низкого качества. Такие тесты не помогают проекту расти, а тянут его вниз. Причина в том, что для их обслуживания и обновления после рефакторинга требуется много времени.
Есть и эффекты второго порядка: вы начинаете терять доверие к своим тестам, что приводит к меньшему количеству рефакторингов и, в итоге, к ухудшению кода.
Всегда обращайте внимание на составляющую затрат. Разрешить только самые ценные тесты в вашем наборе тестов; пренебречь остальным. Лучше иметь небольшой набор очень ценных тестов, чем большое количество посредственных.
Источник: https://enterprisecraftsmanship.com/
Автор оригинала: Vladimir Khorikov
Видимое и Невидимое в Модульном Тестировании
В экономике существует понятие «видимого и невидимого», что означает, что при реализации какой-либо политики необходимо сосредоточить внимание на обеих его сторонах:
- Желаемые результаты, которые являются видимой частью.
- Непредвиденные последствия - невидимая часть.
У вас всегда будет и то, и другое, независимо от реализуемой политики. Решение о том, применять ли политику, сводится к тщательному взвешиванию потенциальных результатов с потенциальными непредвиденными последствиями - видимыми и невидимыми.
То же самое касается разработки программного обеспечения и, в частности, модульного тестирования. При написании тестов следует учитывать как видимые, так и невидимые части.
Видимая часть — это преимущества, которые предоставляют вам модульные тесты. Невидимая часть — это (часто скрытые) затраты.
Обе части критически важны. Затраты более важны, потому что мы, люди, склонны отдавать предпочтение краткосрочным выгодам и пренебрегать долгосрочными затратами. В экономике существует целая теория, называемая теорией предпочтения времени, которая изучает последствия этой тенденции дисконтировать долгосрочную перспективу в пользу краткосрочной.
Видимая часть модульного тестирования - насколько хорошо ваши тесты защищают вас от ошибок. Невидимая - сколько вам стоит эта защита. Компонент затрат состоит из двух основных подкомпонентов:
- Ремонтопригодность (сколько усилий нужно, чтобы тест оставался работоспособным).
- Устойчивость к рефакторингу (сколько шума генерирует этот тест).
Самым большим препятствием для написания хороших тестов является игнорирование затрат на модульное тестирование. В результате люди, как правило, создают много тестов низкого качества. Такие тесты не помогают проекту расти, а тянут его вниз. Причина в том, что для их обслуживания и обновления после рефакторинга требуется много времени.
Есть и эффекты второго порядка: вы начинаете терять доверие к своим тестам, что приводит к меньшему количеству рефакторингов и, в итоге, к ухудшению кода.
Всегда обращайте внимание на составляющую затрат. Разрешить только самые ценные тесты в вашем наборе тестов; пренебречь остальным. Лучше иметь небольшой набор очень ценных тестов, чем большое количество посредственных.
Источник: https://enterprisecraftsmanship.com/
Автор оригинала: Vladimir Khorikov
День 1007. #TipsAndTricks
Как не Стоит Читать Строку из Потока UTF-8
Пост возник после код ревью. Следующий код читает из потока строку в кодировке UTF-8. В реальном контексте код сложнее, здесь только суть:
Один из них - преобразовать массив байт в строку только тогда, когда у вас есть все данные:
Как не Стоит Читать Строку из Потока UTF-8
Пост возник после код ревью. Следующий код читает из потока строку в кодировке UTF-8. В реальном контексте код сложнее, здесь только суть:
string ReadString(Stream stream)Проблема в том, что в некоторых случаях возвращаемая строка отличается от закодированной. Например, иногда смайлик превращается в 4 неизвестных символа:
{
var sb = new StringBuilder();
var buf = new byte[4096];
int readCnt;
while ((readCnt = stream.Read(buf)) > 0)
{
var s = Encoding.UTF8
.GetString(buffer, 0, readCnt);
sb.Append(s);
}
return sb.ToString();
}
В потоке: 😊UTF-8 может использовать от 1 до 4 байт для представления символа, но метод
В результате: ????
Stream.Read
может возвращать байты от 1 до buffer.Length
. Это означает, что буфер может содержать неполный символ UTF-8. В результате Encoding.UTF8.GetString может иметь недопустимую строку UTF-8 для преобразования, поскольку последний символ в буфере может быть неполным. Следующий код имитирует это поведение:var bytes = Encoding.UTF8.GetBytes("😊");Есть несколько способов исправить код.
// bytes = new byte[4] { 240, 159, 152, 138 }
var sb = new StringBuilder();
// Симулируем побайтовое чтение
for (var i = 0; i < bytes.Length; i++)
{
sb.Append(Encoding.UTF8.GetString(bytes, i, 1));
}
Console.WriteLine(sb.ToString());
// "????" вместо "😊"
Encoding.UTF8.GetBytes(sb.ToString());
// new byte[12] { 239, 191, 189, 239, 191, 189, 239, 191, 189, 239, 191, 189 }
Один из них - преобразовать массив байт в строку только тогда, когда у вас есть все данные:
string ReadString(Stream stream)Вы также можете обернуть поток в
{
using var ms = new MemoryStream();
var buf = new byte[4096];
int readCnt;
while ((readCnt = stream.Read(buf)) > 0)
ms.Write(buf, 0, readCnt);
return
Encoding.UTF8.GetString(ms.ToArray());
}
StreamReader
с правильной кодировкой:string ReadString(Stream stream)Источник: https://www.meziantou.net/how-not-to-read-a-string-from-an-utf-8-stream.htm
{
using var sr =
new StreamReader(stream, Encoding.UTF8);
return sr.ReadToEnd();
}
День 1008. #ProjectManagement
3 Принципа Хорошей Разработки ПО. Начало
Понимание особенностей ПО не может гарантировать хороших результатов, но помогает выяснить, почему так много проектов дают плохие результаты. Также они помогают сформулировать некоторые основные принципы работы, которые могут значительно повысить шансы на успех. Хотя необходимо учитывать множество более тонких факторов, следующие принципы образуют основу, позволяющую приступить к созданию хорошего ПО.
1. Начните с самого простого
Проекты, желающие сразу стать «супермаркетом» в определённой области, зачастую обречены. Намерения кажутся разумными: ведь здорово, когда приложение решает как можно больше проблем людей? В конце концов, проще зайти в супермаркет, где есть всё. Разница в том, что в магазин легко добавить новый товар, но приложение с вдвое большим количеством функций создать более чем в два раза сложнее и оно намного сложнее в использовании.
Создание хорошего ПО надо начинать с самого простого решения, которое могло бы решить проблему. В хорошо сделанном, но простом приложении никогда не возникает проблем с добавлением необходимых функций. А большую систему обычно невозможно упростить и исправить. Программные проекты редко терпят неудачу, потому что они слишком малы. Они терпят неудачу, потому что становятся слишком большими. На практике сохранить фокус проекта очень сложно: простой сбор требований от всех заинтересованных сторон уже создает огромный список функций.
Один из способов справиться с этим - использовать список приоритетов. Все требования собираются и помечаются как жизненно важные, важные дополнения или просто полезные функции. Затем заинтересованные стороны могут обсудить, какие функции являются наиболее важными, не беспокоясь о том, что что-то будет упущено. Если кто-то хочет повысить приоритет функции, нужно решить, приоритет каких функций придётся снизить. Команды могут начинать с самых важных задач, продвигаясь вниз по списку, если позволяют время и ресурсы.
2. Нанимайте лучших инженеров
Ключ к хорошей инженерии - это хорошие инженеры. В Google, Facebook, Amazon, Netflix и Microsoft, как известно, одни из самых избирательных процессов собеседований, при этом они ведут ожесточённую борьбу за набор самых сильных кандидатов и платят работникам сильно выше рынка. Этому есть причина. И Стив Джобс, и Марк Цукерберг заявили, что лучшие инженеры как минимум в 10 раз производительнее инженера среднего уровня. Не потому, что они пишут код в 10 раз быстрее, а потому, что они принимают лучшие решения.
Хороший инженер
- лучше разбирается в существующем ПО, которое можно использовать повторно,
- лучше разбирается в инструментах, автоматизируя большинство рутинных задач,
- сам проектирует надёжные и понятные другим системы.
Это имеет мультиплицирующий эффект, позволяя коллегам совершенствовать свою работу. В целом хорошие инженеры намного эффективнее потому, что решения, которые они принимают, избавляют вас от работы, о которой вы не знали, что её можно избежать.
Небольшие команды лучших инженеров эффективно используют доступный открытый код и сложные облачные сервисы и перекладывают рутинные задачи на автоматическое тестирование и другие инструменты, чтобы самим сосредоточиться на творческих аспектах решения проблем. Они быстро тестируют различные идеи с пользователями, расставляя приоритеты по ключевым функциям и исключая неважную работу. Они допускают меньше ошибок и проблем с безопасностью. Проблемы в коде влияют не только на работу автора кода, но и на работу его коллег. В крупных проектах плохие инженеры в итоге создают больше работы друг для друга, из-за ошибок и неправильного выбора решений.
Вот почему самые успешные технологические компании настаивают на самых талантливых специалистах, несмотря на их огромную зарплату. Жёсткий предел сложности системы - не количество инженерных усилий, а их качество.
Окончание следует…
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
3 Принципа Хорошей Разработки ПО. Начало
Понимание особенностей ПО не может гарантировать хороших результатов, но помогает выяснить, почему так много проектов дают плохие результаты. Также они помогают сформулировать некоторые основные принципы работы, которые могут значительно повысить шансы на успех. Хотя необходимо учитывать множество более тонких факторов, следующие принципы образуют основу, позволяющую приступить к созданию хорошего ПО.
1. Начните с самого простого
Проекты, желающие сразу стать «супермаркетом» в определённой области, зачастую обречены. Намерения кажутся разумными: ведь здорово, когда приложение решает как можно больше проблем людей? В конце концов, проще зайти в супермаркет, где есть всё. Разница в том, что в магазин легко добавить новый товар, но приложение с вдвое большим количеством функций создать более чем в два раза сложнее и оно намного сложнее в использовании.
Создание хорошего ПО надо начинать с самого простого решения, которое могло бы решить проблему. В хорошо сделанном, но простом приложении никогда не возникает проблем с добавлением необходимых функций. А большую систему обычно невозможно упростить и исправить. Программные проекты редко терпят неудачу, потому что они слишком малы. Они терпят неудачу, потому что становятся слишком большими. На практике сохранить фокус проекта очень сложно: простой сбор требований от всех заинтересованных сторон уже создает огромный список функций.
Один из способов справиться с этим - использовать список приоритетов. Все требования собираются и помечаются как жизненно важные, важные дополнения или просто полезные функции. Затем заинтересованные стороны могут обсудить, какие функции являются наиболее важными, не беспокоясь о том, что что-то будет упущено. Если кто-то хочет повысить приоритет функции, нужно решить, приоритет каких функций придётся снизить. Команды могут начинать с самых важных задач, продвигаясь вниз по списку, если позволяют время и ресурсы.
2. Нанимайте лучших инженеров
Ключ к хорошей инженерии - это хорошие инженеры. В Google, Facebook, Amazon, Netflix и Microsoft, как известно, одни из самых избирательных процессов собеседований, при этом они ведут ожесточённую борьбу за набор самых сильных кандидатов и платят работникам сильно выше рынка. Этому есть причина. И Стив Джобс, и Марк Цукерберг заявили, что лучшие инженеры как минимум в 10 раз производительнее инженера среднего уровня. Не потому, что они пишут код в 10 раз быстрее, а потому, что они принимают лучшие решения.
Хороший инженер
- лучше разбирается в существующем ПО, которое можно использовать повторно,
- лучше разбирается в инструментах, автоматизируя большинство рутинных задач,
- сам проектирует надёжные и понятные другим системы.
Это имеет мультиплицирующий эффект, позволяя коллегам совершенствовать свою работу. В целом хорошие инженеры намного эффективнее потому, что решения, которые они принимают, избавляют вас от работы, о которой вы не знали, что её можно избежать.
Небольшие команды лучших инженеров эффективно используют доступный открытый код и сложные облачные сервисы и перекладывают рутинные задачи на автоматическое тестирование и другие инструменты, чтобы самим сосредоточиться на творческих аспектах решения проблем. Они быстро тестируют различные идеи с пользователями, расставляя приоритеты по ключевым функциям и исключая неважную работу. Они допускают меньше ошибок и проблем с безопасностью. Проблемы в коде влияют не только на работу автора кода, но и на работу его коллег. В крупных проектах плохие инженеры в итоге создают больше работы друг для друга, из-за ошибок и неправильного выбора решений.
Вот почему самые успешные технологические компании настаивают на самых талантливых специалистах, несмотря на их огромную зарплату. Жёсткий предел сложности системы - не количество инженерных усилий, а их качество.
Окончание следует…
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
День 1009. #ProjectManagement
3 Принципа Хорошей Разработки ПО. Окончание
Начало
3. Ищите проблемы и итерируйте
По правде говоря, современное ПО настолько сложно и меняется так быстро, что никакое планирование не устранит все его недостатки. Чтобы создать хорошее ПО, вам нужно сначала создать плохое, а затем активно искать проблемы, чтобы улучшить своё решение.
Можно поговорить с реальными людьми, которым вы пытаетесь помочь, чтобы понять основную проблему, которую вы хотите решить, и не использовать решение, основанное только на предвзятых предубеждениях.
Остерегайтесь бюрократических целей, маскирующихся под формулировку проблемы. «Пользователи недовольны тем, насколько сложно найти информацию на государственных веб-сайтах», — это проблема. «В рамках плана цифрового правительства нам необходимо перестроить наши веб-сайты, чтобы они соответствовали новым стандартам дизайна», - это не проблема.
Чёткая формулировка проблемы позволяет вам экспериментально проверить жизнеспособность различных решений, которые слишком сложно определить теоретически. Разговаривать с чат-ботом может быть не проще, чем перемещаться по веб-сайту, и пользователи могут не захотеть устанавливать ещё одно приложение на свои телефоны, независимо от того, насколько оно упрощает общение с госорганами. Что касается ПО, очевидные решения часто имеют фатальные недостатки, которые не проявляются до тех пор, пока не будут использованы. Задача не в том, чтобы с первого раза создать идеальный конечный продукт, а в том, чтобы выявить эти проблемы как можно быстрее и с минимальными затратами. Это делается путём создания:
- нефункциональных прототипов для тестирования UI,
- функциональных прототипов для опробования различных функций.
Наспех созданный код прототипа может помочь быстрее получить обратную связь. Всё, что создано на этом этапе, следует рассматривать как одноразовое. Желаемый результат этого процесса - не написанный код, а получить более чёткое понимание того, что нужно создать.
Хорошо понимая правильное решение, вы можете начать работу над созданием реального продукта. Вы прекращаете исследовать новые идеи и фокусируетесь на выявлении проблем, связанных с вашей конкретной реализацией. Начните с небольшого числа тестировщиков, которые быстро обнаружат очевидные ошибки. По мере того, как проблемы решаются, вы можете открывать доступ всё большему количеству людей, которые найдут более экзотические проблемы.
Большинство людей дают обратную связь только один раз. Если вы начнёте с вывода на большую аудиторию, все найдут самые очевидные ошибки, и вам некуда будет дальше идти. Даже лучшие идеи продуктов, созданные лучшими инженерами, начинаются с серьёзных проблем. Цель состоит в том, чтобы многократно улучшать качество продукта, зачищая неровности до тех пор, пока не появится хороший продукт.
Проблемы с продуктом имеют наибольшее значение после запуска. Проблема, которая возникает только в 0,1% случаев, может не быть замечена во время тестирования. Но как только у вас будет миллион пользователей, у вас будет нерешённая проблема с тысячей недовольных людей. Вам необходимо исправить проблемы, вызванные новыми мобильными устройствами, сбоями сети или атаками на систему безопасности, прежде чем они нанесут существенный вред вашим пользователям.
В целом подход заключается в использовании этих различных контуров обратной связи для эффективного выявления проблем. Небольшие контуры позволяют быстро и легко исправить очевидные ошибки, но упускают из виду более широкие проблемы. Большие позволяют выявлять более широкие проблемы, но они медленные и дорогие. Лучше использовать оба, разрешая как можно больше с помощью небольших контуров, при этом сохраняя большие для обнаружения неожиданных ошибок. Создание ПО - это не предотвращение неудач. Это обнаружение стратегического провала как можно быстрее, чтобы получить информацию, необходимую для создания чего-то хорошего.
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
3 Принципа Хорошей Разработки ПО. Окончание
Начало
3. Ищите проблемы и итерируйте
По правде говоря, современное ПО настолько сложно и меняется так быстро, что никакое планирование не устранит все его недостатки. Чтобы создать хорошее ПО, вам нужно сначала создать плохое, а затем активно искать проблемы, чтобы улучшить своё решение.
Можно поговорить с реальными людьми, которым вы пытаетесь помочь, чтобы понять основную проблему, которую вы хотите решить, и не использовать решение, основанное только на предвзятых предубеждениях.
Остерегайтесь бюрократических целей, маскирующихся под формулировку проблемы. «Пользователи недовольны тем, насколько сложно найти информацию на государственных веб-сайтах», — это проблема. «В рамках плана цифрового правительства нам необходимо перестроить наши веб-сайты, чтобы они соответствовали новым стандартам дизайна», - это не проблема.
Чёткая формулировка проблемы позволяет вам экспериментально проверить жизнеспособность различных решений, которые слишком сложно определить теоретически. Разговаривать с чат-ботом может быть не проще, чем перемещаться по веб-сайту, и пользователи могут не захотеть устанавливать ещё одно приложение на свои телефоны, независимо от того, насколько оно упрощает общение с госорганами. Что касается ПО, очевидные решения часто имеют фатальные недостатки, которые не проявляются до тех пор, пока не будут использованы. Задача не в том, чтобы с первого раза создать идеальный конечный продукт, а в том, чтобы выявить эти проблемы как можно быстрее и с минимальными затратами. Это делается путём создания:
- нефункциональных прототипов для тестирования UI,
- функциональных прототипов для опробования различных функций.
Наспех созданный код прототипа может помочь быстрее получить обратную связь. Всё, что создано на этом этапе, следует рассматривать как одноразовое. Желаемый результат этого процесса - не написанный код, а получить более чёткое понимание того, что нужно создать.
Хорошо понимая правильное решение, вы можете начать работу над созданием реального продукта. Вы прекращаете исследовать новые идеи и фокусируетесь на выявлении проблем, связанных с вашей конкретной реализацией. Начните с небольшого числа тестировщиков, которые быстро обнаружат очевидные ошибки. По мере того, как проблемы решаются, вы можете открывать доступ всё большему количеству людей, которые найдут более экзотические проблемы.
Большинство людей дают обратную связь только один раз. Если вы начнёте с вывода на большую аудиторию, все найдут самые очевидные ошибки, и вам некуда будет дальше идти. Даже лучшие идеи продуктов, созданные лучшими инженерами, начинаются с серьёзных проблем. Цель состоит в том, чтобы многократно улучшать качество продукта, зачищая неровности до тех пор, пока не появится хороший продукт.
Проблемы с продуктом имеют наибольшее значение после запуска. Проблема, которая возникает только в 0,1% случаев, может не быть замечена во время тестирования. Но как только у вас будет миллион пользователей, у вас будет нерешённая проблема с тысячей недовольных людей. Вам необходимо исправить проблемы, вызванные новыми мобильными устройствами, сбоями сети или атаками на систему безопасности, прежде чем они нанесут существенный вред вашим пользователям.
В целом подход заключается в использовании этих различных контуров обратной связи для эффективного выявления проблем. Небольшие контуры позволяют быстро и легко исправить очевидные ошибки, но упускают из виду более широкие проблемы. Большие позволяют выявлять более широкие проблемы, но они медленные и дорогие. Лучше использовать оба, разрешая как можно больше с помощью небольших контуров, при этом сохраняя большие для обнаружения неожиданных ошибок. Создание ПО - это не предотвращение неудач. Это обнаружение стратегического провала как можно быстрее, чтобы получить информацию, необходимую для создания чего-то хорошего.
Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
👍1
День 1010.
Ну что ж, время подводить итоги раздачи кружек. Всех желающих отобрал и записал в общий список в порядке появления комментариев. Для выбора победителей использовал простую случайную сортировку.
Результаты на картинке. Поздравляю победителей:
- Dmitriy Bobrovskiy (@RebelionTheGrey)
- Max Kaverin (@Kamaew)
- 𝕾𝖊𝖗𝖌𝖊𝖏 (@Xx_dexter_xX)
- Oleksandr Savchuk (@san_d0)
- Vasily Vasily (@Vasily26031988)
- Matviiv Andriy (@matviiv_a)
- Alexey Chernyaev (@FixGN)
- Georgy Levchenko (@FoxTes)
- Амир Хисматуллин (@ikeima)
Пожалуйста, отпишитесь мне в личку, куда прислать кружки.
Ну что ж, время подводить итоги раздачи кружек. Всех желающих отобрал и записал в общий список в порядке появления комментариев. Для выбора победителей использовал простую случайную сортировку.
Результаты на картинке. Поздравляю победителей:
- Dmitriy Bobrovskiy (@RebelionTheGrey)
- Max Kaverin (@Kamaew)
- 𝕾𝖊𝖗𝖌𝖊𝖏 (@Xx_dexter_xX)
- Oleksandr Savchuk (@san_d0)
- Vasily Vasily (@Vasily26031988)
- Matviiv Andriy (@matviiv_a)
- Alexey Chernyaev (@FixGN)
- Georgy Levchenko (@FoxTes)
- Амир Хисматуллин (@ikeima)
Пожалуйста, отпишитесь мне в личку, куда прислать кружки.
День 1011. #Оффтоп
Давненько вам не рекомендовал видео. Поэтому сегодня в качестве компенсации нечто эпическое. Интервью Сергея Теплякова подкасту DotNet&More:
- Про собеседования
- Какие скилы сейчас важны?
- Работа в команде
- Будущее C#
- SOLID и прочие паттерны. Надо ли оно сейчас?
и про многое другое аж 2,5 часа.
Наслаждайтесь.
https://youtu.be/W7HqDCnQTkU
Давненько вам не рекомендовал видео. Поэтому сегодня в качестве компенсации нечто эпическое. Интервью Сергея Теплякова подкасту DotNet&More:
- Про собеседования
- Какие скилы сейчас важны?
- Работа в команде
- Будущее C#
- SOLID и прочие паттерны. Надо ли оно сейчас?
и про многое другое аж 2,5 часа.
Наслаждайтесь.
https://youtu.be/W7HqDCnQTkU
День 1012. #ЗаметкиНаПолях #AsyncTips
Обработка исключений из методов async Task
Задача
Спроектировать код для успешного результата несложно, но структура кода не может считаться правильной, если в ней не обрабатываются потенциальные ошибки. К счастью, обработка исключений из методов
Решение
Исключения можно перехватывать конструкцией
Это сделано для того, чтобы в простом сценарии использовался простой код. В большинстве случаев код должен распространять исключения из вызываемых асинхронных методов. Всё, что нужно сделать, — использовать
Обработка исключений при ожидании группы задач рассматривалась тут.
Async Void
Что если имеется метод
Хорошего решения не существует. Если возможно, измените метод так, чтобы он возвращал
Существует и другой возможный способ. Когда метод
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
Обработка исключений из методов async Task
Задача
Спроектировать код для успешного результата несложно, но структура кода не может считаться правильной, если в ней не обрабатываются потенциальные ошибки. К счастью, обработка исключений из методов
async Task
реализуется прямолинейно.Решение
Исключения можно перехватывать конструкцией
try/catch
, как для синхронного кода:async Task ThrowExceptionAsync()Исключения, выданные из методов
{
await Task.Delay(TimeSpan.FromSeconds(1));
throw new InvalidOperationException("Test");
}
async Task TestAsync()
{
try {
await ThrowExceptionAsync();
}
catch (InvalidOperationException) {…}
}
async Task
, помещаются в возвращаемый объект Task
. При использовании await с задачей, в которой произошёл отказ, первое исключение этой задачи выдаётся повторно. При этом исходная трассировка стека будет правильно сохранена.Это сделано для того, чтобы в простом сценарии использовался простой код. В большинстве случаев код должен распространять исключения из вызываемых асинхронных методов. Всё, что нужно сделать, — использовать
await
с задачей, возвращённой из асинхронного метода, и это исключение будет распространяться естественным образом.Обработка исключений при ожидании группы задач рассматривалась тут.
Async Void
Что если имеется метод
async void
и требуется обработать исключения, распространённые из этого метода.Хорошего решения не существует. Если возможно, измените метод так, чтобы он возвращал
Task
вместо void
. Если вам требуется использовать метод async void
, рассмотрите возможность упаковки всего кода метода в блок try/catch
.Существует и другой возможный способ. Когда метод
async void
распространяет исключение, это исключение выдаётся в контексте SynchronizationContext
, активном на момент начала выполнения метода async void
. Если среда выполнения предоставляет SynchronizationContext
, то обычно она предоставляет механизм обработки этих высокоуровневых исключений на глобальном уровне. Например, WPF предоставляет Application.DispatcherUnhandledException
, а ASP.NET — UseExceptionHandler
.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
День 1013. #ЧтоНовенького
Новые Способы Организовать Вкладки в VS 2022
В Visual Studio 2022 появилась возможность раскрашивать вкладки по проектам, чтобы было легче ориентироваться в открытых файлах. Для этого перейдите в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна) и выберите Colorize tabs (Раскрасить вкладки). Есть возможность раскрашивать по проектам и скоро появится возможность раскрашивать по типам файлов.
Вертикальные вкладки
Чтобы включить эту функцию, щёлкните правой кнопкой мыши любую вкладку и выберите Set Tab Layout > Place Tabs on the Left (Расположение Вкладок > Разместить Слева).
Гибкая настройка
Также добавили параметры, чтобы выделить активную вкладку жирным шрифтом, изменить максимальную/минимальную ширину вкладки и добавить дополнительную кнопку закрытия вверху документа. Это также можно сделать в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна).
Источник: https://devblogs.microsoft.com/visualstudio/personalize-docs/
Новые Способы Организовать Вкладки в VS 2022
В Visual Studio 2022 появилась возможность раскрашивать вкладки по проектам, чтобы было легче ориентироваться в открытых файлах. Для этого перейдите в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна) и выберите Colorize tabs (Раскрасить вкладки). Есть возможность раскрашивать по проектам и скоро появится возможность раскрашивать по типам файлов.
Вертикальные вкладки
Чтобы включить эту функцию, щёлкните правой кнопкой мыши любую вкладку и выберите Set Tab Layout > Place Tabs on the Left (Расположение Вкладок > Разместить Слева).
Гибкая настройка
Также добавили параметры, чтобы выделить активную вкладку жирным шрифтом, изменить максимальную/минимальную ширину вкладки и добавить дополнительную кнопку закрытия вверху документа. Это также можно сделать в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна).
Источник: https://devblogs.microsoft.com/visualstudio/personalize-docs/