Статті

  • Побрехенькі про імена у які вірять програмісти

    Це переклад доволі старої і дуже відомої статті з 2010 року про неявні припущення які роблять програмісти при праці із іменами.

    Сьогодні Джон Ґрем-Каммінґ написав статтю, в якій поскаржився на те, що комп’ютерна система, з якою він працював, визначила його прізвище як таке, що містить неприпустимі символи. Звісно, це не так - адже будь-що, що людина називає своїм іменем, за визначенням є правильним способом її ідентифікації. Ця ситуація закономірно обурила Джона, і він має на це повне право, бо імена - це основа нашої ідентичності, майже за визначенням.

    Я кілька років жив у Японії, працюючи програмістом на професійному рівні, і зламав чимало систем просто тим, що моє ім’я було до них додано. (Більшість людей називають мене Патрік МакКензі, але я визнаю правильними щонайменше шість різних “повних” імен, і багато з систем, з якими я маю справу, не приймають жодного з них.) Я також працював з Великими Чортовими Корпораціями, які, з огляду на глобальний характер свого бізнесу, теоретично побудували свої системи так, щоб підтримувати всі можливі імена. Однак я жодного разу не бачив комп’ютерної системи, яка правильно працювала б з іменами, і щиро сумніваюся, що така взагалі існує.

    Тож, як суспільну послугу, я наведу список припущень, які, ймовірно, роблять ваші системи щодо імен. Усі ці припущення - хибні. Спробуйте уникати їх наступного разу, коли писатимете систему, яка працює з іменами.

    1. У кожної людини є рівно одне канонічне повне ім’я.
    2. У кожної людини є рівно одне повне ім’я, яким вона користується.
    3. На даний момент у людини є рівно одне канонічне повне ім’я.
    4. На даний момент у людини є одне повне ім’я, яким вона користується.
    5. У кожної людини є рівно N імен, для будь-якого значення N.
    6. Імена людей вміщаються у певну заздалегідь визначену кількість символів.
    7. Імена людей не змінюються.
    8. Імена людей змінюються лише при певних перелічених подіях.
    9. Імена людей пишуться лише символами ASCII.
    10. Імена людей записані в одному певному наборі символів.
    11. Імена людей завжди можна представити у вигляді Unicode-кодів (code-points).
    12. Імена людей чутливі до регістру.
    13. Імена людей нечутливі до регістру.
    14. В іменах людей іноді є префікси чи суфікси, але їх можна безпечно ігнорувати.
    15. Імена людей не містять цифр.
    16. Імена людей не пишуться ВЕЛИКИМИ ЛІТЕРАМИ.
    17. Імена людей не пишуться лише малими літерами.
    18. Імена мають певний порядок. Вибравши будь-яку схему впорядкування, можна забезпечити узгоджене впорядкування між усіма системами - якщо всі вони використовують одну й ту ж схему.
    19. Ім’я та прізвище людини обов’язково різні.
    20. У всіх людей є прізвище, родове ім’я або щось подібне, що поділяють люди, визнані їхніми родичами.
    21. Імена людей є глобально унікальними.
    22. Імена людей майже глобально унікальні.
    23. Добре, добре, але ж, напевно, імена достатньо різноманітні, щоб мільйон людей не мали однакового імені.
    24. Моя система ніколи не буде мати справу з іменами з Китаю.
    25. Або з Японії.
    26. Або з Кореї.
    27. Або з Ірландії, Великої Британії, США, Іспанії, Мексики, Бразилії, Перу, Росії, Швеції, Ботсвани, Південної Африки, Тринідаду, Гаїті, Франції чи Імперії Клінгонів - усі з яких мають “дивні” схеми іменування.
    28. Імперія Клінгонів - це жарт, так?
    29. Досить цього культурного релятивізму! Принаймні в моєму суспільстві є загальноприйнятий стандарт для імен.
    30. Існує алгоритм, який може перетворювати імена та повертати їх назад без втрат. (Так, так, якщо алгоритм просто повертає вхід - молодець, тримай пиріжок.)
    31. Я можу з упевненістю припустити, що в цьому словнику лайливих слів немає жодного імені.
    32. Імена людям надаються при народженні.
    33. Гаразд, може не при народженні, але принаймні близько до нього.
    34. Ну добре, хоча б протягом року після народження.
    35. П’ять років?
    36. Та ви жартуєте, так?
    37. Дві різні системи, що зберігають дані про одну й ту ж людину, використовуватимуть для неї однакове ім’я.
    38. Два різні оператори введення даних, отримавши ім’я людини, обов’язково введуть ідентичні рядки на одній системі, якщо система добре спроєктована.
    39. Люди, чиї імена ламають мою систему - це дивні винятки. Вони мали б мати нормальні, прийнятні імена, на кшталт 田中太郎.
    40. У всіх людей є імена.

    Цей список далеко не вичерпний. Якщо вам потрібні приклади реальних імен, які спростовують будь-яке з наведених вище поширених припущень - я з радістю познайомлю вас з кількома. Не соромтеся додавати інші хибні уявлення в коментарях - і обов’язково показуйте цю статтю кожного разу, коли хтось пропонує «геніальну» ідею на кшталт створення таблиці бази даних з полями first_name та last_name.

  • Шаблони використання LLM - Шаблон когнітивного верифікатора

    Це сьома стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Шаблон альтернативні підходи

    Намір і контекст

    Дослідниками описано, що LLM часто можуть думати краще, якщо питання розділено на додаткові запитання, які дають відповіді, об’єднані в загальну відповідь на початкове запитання. Намір шаблону полягає в тому, щоб змусити LLM завжди ділити питання на додаткові запитання, які можна використовувати для надання кращої відповіді на вихідне запитання.

    Мотивація

    У шаблону когнітивного верифікатора є подвійна мотивація:

    • Люди можуть спочатку ставити запитання занадто високого рівня, щоб дати конкретну відповідь, без залучення додаткових уточнювань, через незнайомість користувача із доменом, лінь у швидкому введенні або невпевненість у правильному формулюванні запитання.
    • Дослідження показали, що LLM часто можуть працювати краще, якщо використовувати запитання, яке підрозділяється на окремі питання.
  • Simple use case for property based testing

    Here we go property-based testing. It’s usually topic which does not have too much discussion on the Internet, and when it is discussed there not much practical aspects to it. It’s relatively well known that you should wrote your invariants and test agains them. This is all fine, but does not give you idea about what exactly these properties of your models are.

    So here our problem. The path normalization. This is art of conversion of paths road/path/../to/hell/ to road/to/hell, or skip/me/./if/you/can to skip/me/if/you/can, or ../../../only/forward/no/backwards. Basically simplification of paths. That can be very tricky business. For example, ././test is just test, or /../some/ is really wrong path, but we have to leave it as is because it appear as absolute path.

    Whole excercise would be performed over TruePath which is library for static typing when working with paths.

    FsCheck

    For this demonstation I would use FsCheck which is library written in F#, but for this article I would use C#, since that’s language which TruePath is written in. Since TruePath uses XUnit for the testing, I would use FsCheck.Xunit integration package, which simplifies writing FsCheck tests for Xunit. Update 2025/06/06, since I decide that F# is interesting enough, I create Gist where same code expressed in F#

    When testing using FsCheck, your most important thing would be write generators for our test data. In that sense property based testing is very similar to fuzzing, with only difference is that we have a bit more statements abour our code then simple It does not crash.

    Model

    Let’s start with our example. I decide that it would be beneficial to model paths as list of following tokens:

    • Volume marker (optional)
    • Path part consisting from letters or numbers
    • Current directory block .
    • Parent directory block ..
    • Three dots block ... to spice things for the library a bit
    • Directory separate and alternative directory separators as specified in Path.DirectorySeparatorChar or Path.AltDirectorySeparatorChar

    Because it’s C# with lack of expressivity, I decide that I can model these tokens as simple List<string>, in the F# probably I would go with array of unions, or so. But it’s 2025 and we still waiting for unions in C#.

    Generation

    Let’s start generating our tokens. Let’s add namespaces which we need in C#.

    using FsCheck;
    using FsCheck.Fluent;
    

    and start with simplest generators, which always generate constants.

    var baseDir = Gen.Constant("..");
    var currentDir = Gen.Constant(".");
    var threeDots = Gen.Constant("...");
    

    Obviosly we don’t want generate constant, so let’s combine these generators into one which randomly generate either of them.

    var dots = Gen.OneOf([baseDir, currentDir, threeDots]);
    

    Now let’s generate path separators.

    var directorySeparatorChar = Gen.Constant(Path.DirectorySeparatorChar).Select(c => c.ToString());
    var altDirectorySeparatorChar = Gen.Constant(Path.AltDirectorySeparatorChar).Select(c => c.ToString());
    

    It’s same call to Gen.Constant but since Path.DirectorySeparatorChar and Path.AltDirectorySeparatorChar both have type char, but we want our tokens we map then to string type using Select method.

    Now let’s generate path parts. We want generate non-empty sequence of the lowercase characters, or uppercase characters or digits. Let’s express that. Start with generation of lower-case charaters, that would be using Gen.Choose method like this Gen.Choose('a', 'z'). Similar for upper case characters would be Gen.Choose('A', 'Z') and for digits would be Gen.Choose('0', '9'). Now we can chain these generator declarations then using .Or method. So characters which would be parts of the path would be represented like this.

    Gen.Choose('a', 'z')
        .Or(Gen.Choose('A', 'Z'))
        .Or(Gen.Choose('0', '9'))
    

    In order to generate non-empty sequence we have to use Gen.NonEmptyListOf.

    var textPath = Gen.NonEmptyListOf(Gen.Choose('a', 'z').Or(Gen.Choose('A', 'Z')).Or(Gen.Choose('0', '9'))).Select(l => string.Join("", l.Select(c => (char)c)));
    

    Attentive reader would notice that we have some tail with conversion. It’s a bit of inconvenence, but Gen.Choose produce only ints within range, so the call to Gen.NonEmptyListOf would produce Gen<List<int>> but we really want produce Gen<string> so we have to map resulting type to string using Select method.

    Now we known everything to produce list of token. Let’s do that

    var pathGenerator = Gen.NonEmptyListOf(Gen.OneOf([dots, directorySeparatorChar, altDirectorySeparatorChar, textPath]))
    

    That’s seems to be what we need, and there no way to guess that initiall, but that a bit invonvinient generator for pracical work. When we build this simple model, we want to operate on tokens, plus we want simple way to build path out of it. For example just by concatenation of strings. And naive generator would not work, since we can have following sequence ['..', '.'] and combining it, would change meaning of the tokens. So to simplify future post processing during writing test I will filter out combination where consequetive tokens have . in them. I use Where method for this.

    var pathGenerator = Gen.NonEmptyListOf(Gen.OneOf([dots, directorySeparatorChar, altDirectorySeparatorChar, textPath]))
        .Where(l =>
        {
            for (int i = 0; i < l.Count - 1; i++)
            {
                // Avoid consecutive dots like "..../.."
                if (l[i][0] == '.' && l[i + 1][0] == '.') return false;
            }
    
            return true;
        })
    

    Now we have everything to build Linux path generator. So let’s see how it looks when combined together.

    using FsCheck;
    using FsCheck.Fluent;
    
    //....
    
    internal static class PathGenerators
    {
        public static Gen<List<string>> LinuxPathItemsGenerator()
        {
            var baseDir = Gen.Constant("..");
            var currentDir = Gen.Constant(".");
            var threeDots = Gen.Constant("...");
            var dots = Gen.OneOf([baseDir, currentDir, threeDots]);
            var textPath = Gen.NonEmptyListOf(Gen.Choose('a', 'z').Or(Gen.Choose('A', 'Z')).Or(Gen.Choose('0', '9'))).Select(l => string.Join("", l.Select(c => (char)c)));
    
            var directorySeparatorChar = Gen.Constant(Path.DirectorySeparatorChar).Select(c => c.ToString());
            var altDirectorySeparatorChar = Gen.Constant(Path.AltDirectorySeparatorChar).Select(c => c.ToString());
            return Gen.NonEmptyListOf(Gen.OneOf([dots, directorySeparatorChar, altDirectorySeparatorChar, textPath]))
                .Where(l =>
                {
                    for (int i = 0; i < l.Count - 1; i++)
                    {
                        // Avoid consecutive dots like "..../.."
                        if (l[i][0] == '.' && l[i + 1][0] == '.') return false;
                    }
    
                    return true;
                });
        }
    }
    

    Now we can. based on this generator build Windows path generator

    public static Gen<List<string>> WindowsPathItemsGenerator()
    {
        var driveLetter = Gen.Choose('a', 'z').Or(Gen.Choose('A', 'Z')).Select(c => (char)c + ":");
        var directorySeparatorChar = Gen.Constant(Path.DirectorySeparatorChar).Select(c => c.ToString());
        var altDirectorySeparatorChar = Gen.Constant(Path.AltDirectorySeparatorChar).Select(c => c.ToString());
        var separator = Gen.OneOf([directorySeparatorChar, altDirectorySeparatorChar]);
        var drivePrefix = Gen.Zip(driveLetter, separator).Select(static t =>
        {
            var (driveLetter, separator) = t;
            return driveLetter + separator;
        });
        return Gen.Zip(drivePrefix, LinuxPathItemsGenerator()).Select(static t =>
        {
            var (prefix, items) = t;
            items.Insert(0, prefix);
            return items;
        });
    }
    

    The only new thing here is Gen.Zip which takes two generator and create generator of tuples. We use that to concat output of generators for drive name and directory separators.

    Arbitraries (or domain models)

    Myabe I’m wrong, but currently I look at types which provide Arbitrary<T> static functions as types which decribe domain concepts, and each function represent different variants of this concept. It’s usually described as combination of generator + shrinker (another not need for now concept), and that’s technically true, but I think that’s does not help learning. So please trust me for now, and if down the road, you will think that I’m wrong, come back and let me know to not teach people wrong things.

    For this test I will use very simple arbitraty class definition

    public class AnyOsPath
    {
        public static Arbitrary<List<string>> Paths()
        {
            return Arb.From(Gen.Or(PathGenerators.LinuxPathItemsGenerator(), PathGenerators.WindowsPathItemsGenerator()));
        }
    }
    

    I create Arbitrary from generator which either have Linux or Windows path. I do not combine them, since eventually I need this difference, but not in this article. I don’t use anything else when define Arbitrary because I rely on fact that List and string already have their suppport machinery and FsCheck will do things properly for this small model.

    Invariants

    Okay, here the juice. Our invariants. I manage to create some invariants which path normalization in this specific library hold. It make sense from general perspective too. Here them:

    • Normalized path never ends with DirectorySeparatorChar.
    • Normalized path never contains AltDirectorySeparatorChar.
    • Normalized path does not have two consequetive path separators
    • Relative depth of the path preserved after normalization.

    Let me explain a bit. First one rule is very simple, If I have absolute or relative paths then normalized path, never have DirectorySeparatorChar at the end. For example /test/ would be normalized to /test. Second is simple as well, whenether I have path with AltDirectorySeparatorChar, these charaters replaced with DirectorySeparatorChar, for example, c:/test would be normalized into c:\test. Next one also simple. We collapse all directory separator into single separator, for example, /test//subfolder is really /test/subfolder. Last one a bit tricky. I want make sure that if relative depth of path was pointed to N levels depth it would be preserved in the normalized paths. For example, some/path has relative depth 2, some/../path have relative depth 1, and after nomalization become simply path which also have relative depth 1. So here the idea.

    Let’s show how I wrote test for invariants. I will start with second invariant, since it’s most simple

    [Property(Arbitrary = new[] { typeof(AnyOsPath) })]
    public void NormalizedPathDoesContainAltDirSeparator(List<string> pathParts)
    {
        var sourcePath = string.Join("", pathParts);
    
        // Act
        var normalizedPath = PathStrings.Normalize(sourcePath);
    
        Assert.True(!normalizedPath.Contains(Path.AltDirectorySeparatorChar));
    }
    

    Here I define test using Property attribute, and specify that parameters to the methods would use Arbitrary methods from type AnyOsPath. All magic in the Property attribute, and the body of the test is trivial once you come up with invariant simple enough.

    Now let’s back to first invariants.

    [Property(Arbitrary = new[] { typeof(AnyOsPath) })]
    public void NormalizedPathDoesNotEndWithDirSeparator(List<string> pathParts)
    {
        var sourcePath = string.Join("", pathParts);
    
        // Act
        var normalizedPath = PathStrings.Normalize(sourcePath);
    
        Assert.True(normalizedPath == ""
            || normalizedPath == Path.DirectorySeparatorChar.ToString()
            || (normalizedPath.Length == 3 && normalizedPath[1] == ':')
            || normalizedPath[^1] != Path.DirectorySeparatorChar);
    }
    

    As can be seen, invariant not so simple and have couple exclusion from rules. For example root path is perfectly normalized path /, but it has DirectorySeparatorChar at the end. Same for the Windows paths C:\. But that’s basically it.

    Third invariant similarly simple as second one, so I omit it here. So let’s see the last one.

    [Property(Arbitrary = new[] { typeof(AnyOsPath) })]
    public void DepthPreserverd(List<string> pathParts)
    {
        var sourcePath = string.Join("", pathParts);
    
        // Act
        var normalizedPath = PathStrings.Normalize(sourcePath);
    
        // Simplified normalization logic over our model.
        var collapsedBlock = CollapseSameBlocks(pathParts);
    
        var expectedDepth = CountDepth(collapsedBlock);
        var actualDepth = CountDepth([.. normalizedPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)]);
        Assert.Equal(expectedDepth, actualDepth);
    
        // Function which count relative depth of the base
        static int CountDepth(List<string> pathParts)
        {
            int depth = 0;
            foreach (var part in pathParts)
            {
                if (part == Path.DirectorySeparatorChar.ToString() || part == Path.AltDirectorySeparatorChar.ToString())
                {
                    continue;
                }
    
                // Skip home drive which does not affect depth.
                if (part.Contains(':'))
                {
                    continue;
                }
    
                if (part == "..")
                {
                    if (depth > 0)
                    {
                        depth--;
                    }
                }
                else if (part != ".")
                {
                    depth++;
                }
            }
            return depth;
        }
    }
    

    So what I did here. First I simplify generated model

    // Simplified normalization logic over our model.
    var collapsedBlock = CollapseSameBlocks(pathParts);
    

    That’s important part why we create model in itself, to be able create simpler rules. Also that’s why I remove consequetive .. and . tokens from the list. To be able write this CollapseSameBlocks function without overly complicated logic. If you interested in the logic in this function, you can take a look at the implementation in the PR.

    Then I create local function for calculation local depth static int CountDepth(List<string> pathParts), and after that test become trivial. Tha’s the gusto, find proper simple model which can represent your complicated domain. In our case list of tokens was good enough.

    Summary

    Hopefully this was interesting and practical enough example of property based testing. You can take a look at the code in the PR. Some invariants explained in this article submitted as separate PR, but that should not hinder you.

  • Думки про безпеку аплікацій

    Мене вже давно турбує питання, що, як на мене, спеціалісти з безпеки недостатньо добре працюють у напрямку популяризації своїх ризиків та навчання людей побудові безпечних рішень.

    Мій тезис полягає в тому, що фахівці з безпеки просто не бачать складності навчального процесу і не враховують педагогічні досягнення, які ми бачимо і до яких звикли в інших сферах ІТ. Ми звикли до цього комфорту і не хочемо напружуватися більше, ніж потрібно. А потреба в безпеці не завжди яскраво виражена в нашій роботі, що створює конфлікт інтересів.

    Нижче я приведу декілька прикладів які на мою думку показують що спільнота мов програмування вчить своїх людей краще ніж безпечники.

  • Шаблони використання LLM - Шаблон альтернативні підходи

    Це шоста стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Шаблон альтернативні підходи

    Намір і контекст

    Мета шаблону полягає в тому, щоб LLM завжди пропонував альтернативні способи виконання завдання, щоб користувач не використовував лише ті підходи, з якими він знайомий. LLM може пропонувати альтернативні підходи, які завжди змушують користувача думати про те, що він робить, і визначати для себе, чи це найкращий підхід для досягнення мети. Крім того, вирішення завдання може проінформувати користувача або навчити його альтернативним концепціям для подальшої роботи.

    Мотивація

    Люди часто страждають від когнітивних упереджень, які змушують їх обирати певний підхід до вирішення проблеми, навіть якщо це не є правильним або «найкращим» підходом. Більше того, люди можуть не знати про альтернативні підходи до тих, що вони використовували в минулому. Мотивація шаблону Альтернативні підходи полягає в тому, щоб забезпечити обізнаність користувача про альтернативні підходи для вибору кращого підходу до вирішення проблеми шляхом усунення його когнітивних упереджень.

  • OpenWebIndex - Европейський індекс вебу

    У вересні 2022 року партнери розпочали реалізацію проєкту ЄС OpenWebSearch.eu — першого проєкту, який ЄС профінансував для запуску незалежного веб-пошуку.

    Проєкт виник як відповідь на занепокоєння ЕС щодо дисбалансу на ринку пошукових систем. Веб-пошук є основою цифрової економіки, але він перебуває під контролем обмеженої кількох гравців, таких як Google, Microsoft, Baidu або Yandex, які всі знаходяться за межами ЕС. Таким чином, інформація як суспільне благо, з вільним, неупередженим і прозорим доступом, більше не знаходиться під контролем европейского суспільства. Цей дисбаланс становить загрозу для демократії в межах ЕС та обмежує інноваційний потенціал дослідницького простору та економіки самого ЕС. Через це ЕС вирішив проінвестувати в розвиток незалежної, більш децентралізованої інфраструктури для пошуку в мережі Інтернет.

  • Мексика үкіметінде ашық кодты қолдану тәжірибесі

    Бұл мақаланың аудармасы LWN.NET сайтынан.

    Ашық бастапқы кодты бағдарламалық қамтамасыз етуді, үкіметтің бағдарламаны қабылдағаны әртүрлі жетістіктер мен сәтсіздіктерге ұшырады. Ашық код айқын таңдау сияқты көрінгенімен, үкіметтер түрлі себептермен еркін және ашық бастапқы кодты бағдарламалық қамтамасыз етуді (FOSS) қабылдауға күтпеген қарсылық көрсетуі мүмкін. Федерико Гонсалес Уэйт SCALE 22x шарасында Open Government конференциясында өзінің Мексика үкіметімен жұмыс тәжірибесін баяндады. Ол бірнеше жобаларды басқарды, олардың мақсаты меншік құқығындағы, жиі қанаушылық сипаттағы бағдарламалық компаниялардан көшу болатын, кейбір табыстармен және сәтсіздіктермен.

    Гонсалес Уэйт өзінің мексикалық/киви екенін айтты ("біздей адамдар көп емес", деді ол ұялып), және Мексика үкіметінде тоғыз немесе он жыл жоғары лауазымдарда жұмыс істегенін айтты, "ашық кодты енгізуді ілгерілеткен". Ол, басқалармен қатар, Сыртқы істер министрлігінің CTO-сы болды; "Бүгінде мексикалықтардың электронды төлқұжаттары бар болса, бұл менің жұмысымның арқасы". Бұл оның басқарған жобаларының бірі болды, және оның бір бөлігі ашық бастапқы кодты бағдарламалық қамтамасыз етумен жасалды, бұл көпшілікті таң қалдырғанын айтты. Ол сондай-ақ президент Андрес Мануэль Лопес Обрадор кезіндегі ұлттық стратегия офисінде жұмыс істеді және кейінірек Мексиканың Ұлттық зерттеулер мен инновациялар орталығының бас директоры болды.

    Барлық қызметтерінде ол үкіметте ашық кодты қолдануды қолдады; осындай ауқымда өзгеріс енгізу әрқашан оңай емес, деп атап өтті ол. Жақында президент ауысқаннан кейін (Клаудия Шейнбаумға) ол үкіметтен кетті және қазір "адамдарға өздерінің ашық кодқа көшуін жүзеге асыруға көмектеседі", әрі жаңа негізгі тенденцияларды бақылап отыр. Ол сұрақтарға соңында жауап беретінін айтты, бірақ кейбір сұрақтарға құпиялық міндеттемелері себебінен жауап бере алмауы мүмкін, дегенмен "ол мемлекеттік қызметкер болмағандықтан, еркін сөйлеу мүмкіндігі көбірек" екенін атап өтті.

  • MagicMapper: The fork of AutoMapper

    Recent changes in the AutoMapper license, and the waves which this send across .NET chats and subreddits make me think. Why even look for alternatives to AutoMapper? I really have erratic feelings about that and it rubs me wrong way. AutoMapper was free and useful software for a long time. Jimmy really do great job maintainig it, and even coming out as guy who want a bit more money was done in very professional way.

    So why not even create a fork given that AutoMapper have MIT license?

    Is across whole .NET community not enough developers who have two things, a bit of free time, and a bit of charitable character to maintain things. Why send ripples across bunch of products and perform meaningless rewrites? If you think about it, if you want replace AutoMapper with Mapperly you somehow should justify it. Prefereably as business developers say, that should have business impact. Some fearmongering that “maybe” something happens is not really a justification, because obviosuly Mapperly after sometime may go out of OSS business. Maybe not, but we don’t know. Is rewriting to anything else, not nescessary Mapperly obviously, a reasonable investment, or you can just fork existing working product, with excellent maintainance infrastructure and call it a day.

    But just forking is not maintaining!

    Yes, sure. But how often you expect anything new from AutoMapper as was super happy with new release? From what I know Jimmy don’t really cooperate much with outsiders. That’s his project, cannot blame him on choosing safe way to engage with users. What kind of improvements do you really expect? If you have one, and want spend cycles discussing how you can improve something, let me know.

    Now to maintaining. I really don’t see this as high maintainaince project. You can really go very far with allowing people contribute and submit PR + tests. Existing tests very solid. Just adopt policy to never change existing tests and never break them. That’s easy. Improving would be harder, but you know, who cares… That’s maintainance and we in .NET and not in JavaScript where Mark’s Zuckerberg shouting ‘Move fast and break everything’ from every corner.

    I want improvements!

    So do I. My personal wish for AutoMapper is to be able use it in NativeAOT. Honesly given it’s very liberal use of reflection, I did not try to do that on my NativeAOT fixing spree. I thinking that Jimmy would not want to re-engeneer library to make it support NativeAOT. Maybe I was wrong, but given that I have perception that it would not answer I do not even try. Probably this is golden opportunity. Maybe that allow me to make NativeAOT more friendly to corporate codebases. I know that NativeAOT is painful, and the more libraries will support it in some fashion, the better for everybody. I never understand some decisions which Microsoft developers did back then, and now I painfully realize that this is proper decisions, even if NativeAOT is not that extreme and agressive as it can be. Kudos for caring about community THAT much.

    So in short, expect some source generator experiments. I know that support everything would be impossible, but let’s try to poke that. That would be in separate branch probably.

    Statement

    I create fork, and call it MagicMapper, it’s on Nuget, I do not fully migrate on it my projects, but I will.

    I at minimum plan to maintain this fork for an year. Most likely more. I’m much more liberal to transferring ownership to the project to other, so in case I would be missing or unable to, I think it would be possible to continue work on the project for anybody else, without disruption by other.

    I do try my best to have spirit of OSS running on this project. I want that fork to be solution for independent developers. For somebody to remember, I hope it can be revitalization of Alt.Net movement.

    Personally I more dislike AutoMapper then like it. The only reason why I dislike it, is that it breaks tooling and if using without moderatin it’s easy to make things worse. That don’t reason to abandon library in my opinion, we should preserve too. What I learn during my years in software development is that rewriting is always worst decision then evolution.

    What about other projects?

    In addition to AutoMapper there MediatR and MassTransit. Honesly I never think about forking them, but jokes from my friends that I fork everything what can be forked sometimes make sense. I think I have limited time to maintain, and cannot do that alone, so if somebody think that’s worth it, I may reconsider my involvement. AutoMapper can live on life support, but MediatR is next level, and MassTransit is definitely even more harder.

    Acknoledgment

    I fully aknowledge hard work which Jimmy Bogard did on AutoMapper. I would like to thank you him! I personally don’t envision how my fork can endanger his future business or AutoMapper as commercial thing. I think there can be space for both options in the .NET ecosystem.

    Call for help

    I still not done transferring documentation to some other location, and make sure that all links point to proper location, and other housekeeping things. If you want help, go to Github and start hacking.

  • Шаблони використання LLM - Шаблон уточнення питання

    Це п’ята стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Шаблон уточнення питання

    Намір і контекст

    Цей шаблон залучає LLM до процесу розробки запиту. Мета цього шаблону полягає в тому, щоб розмовний LLM завжди пропонував потенційно кращі або більш рафіновані запитання, які користувач міг би поставити замість свого початкового запитання. Використовуючи цей шаблон, LLM може допомогти користувачеві знайти правильне питання, щоб отримати точну відповідь. Крім того, LLM може допомогти користувачеві знайти інформацію або досягти його мети за меншу кількість взаємодій з користувачем, ніж якби користувач використовував підказки методом проб і помилок.

    Мотивація

    Якщо користувач ставить запитання, можливо, він не є фахівцем у цій галузі та може не знати, як найкраще сформулювати запитання, або не знати про додаткову інформацію, яка допоможе сформулювати запитання. LLM часто зазначають обмеження щодо відповіді, яку вони надають, або запитують додаткову інформацію, щоб допомогти їм отримати більш точну відповідь. LLM може також висловити припущення, які він зробив, надаючи відповідь. Мотивація полягає в тому, що цю додаткову інформацію або набір припущень можна використати для створення кращого підказки. Замість того, щоб вимагати від користувача переварити та перефразувати своє підказку з додатковою інформацією, LLM може безпосередньо вдосконалити підказку, щоб включити додаткову інформацію.

  • Досвід із використання відкритого коду в уряді Мексики

    Це переклад статті із LWN.NET

    Прийняття урядами програмного забезпечення з відкритим вихідним кодом мало як злети, так і падіння. Хоча відкритий код здається очевидним вибором, виявляється, що уряди можуть бути дивно опірними до використання вільного ПЗ з відкритим кодом (FOSS) з різних причин. Федеріко Гонсалес Уейт виступив на конференції Open Government на SCALE 22x у Пасадені, Каліфорнія, щоб згадати свій досвід роботи із та на мексиканський уряд. Він очолював декілька проєктів, що передбачали перехід від пропріетарних, часто хижацьких, програмних компаній, з певним успіхом і також невдачами.

    Гонсалес Уейт почав з того, що він є мексиканцем/ківі ("не так много таких як ми", сказав він зашарівшись), який провів дев’ять або десять років на високих посадах у мексиканському уряді, «просуваючи впровадження відкритого коду». Серед іншого він був CTO у Міністерстві закордонних справ; «Я фактично відповідаю за те, що сьогодні мексиканці мають електронні паспорти». Це був один з проєктів, яким він керував, і частина його була виконана за допомогою ПЗ з відкритим кодом, що люди вважають дивовижним, за словами Гонсалеса Уейта. Він працював в офісі національної стратегії при президенті Андресі Мануелі Лопесі Обрадорі, а згодом став генеральним директором Національного центру досліджень і інновацій Мексики.

    У всіх своїх ролях він виступав за використання відкритого коду в уряді; бути «змінювачем» такого масштабу завжди нелегко, зазначив він. Він залишив уряд після недавньої зміни президента (на Клаудію Шейнбаум) і зараз працює «допомогаючи людям здійснювати власні трансформації» до відкритого коду, водночас слідкує за наступними великими тенденціями. Він зазначив, що відповість на запитання в кінці, але можливо не зможе відповісти на всі через конфіденційні зобов’язання, проте він «вже не є публічним посадовцем, тому це дає мені більше свободи говорити відкрито».

  • Шаблони використання LLM - Шаблон персона

    Це четверта стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Шаблон персона

    Намір і контекст

    У багатьох випадках користувачі бажають, щоб результат LLM завжди мав певну точку зору або перспективу. Наприклад, може бути корисно провести перевірку коду так, ніби LLM є експертом з безпеки. Намір цього шаблону полягає в тому, щоб надати LLM «особистість», яка допомагає вибирати які типи результатів генерувати та на яких деталях зосереджуватися.

    Мотивація

    Користувачі можуть не знати, на яких видах результатів або дрібницях важливо зосередитися LLM для досягнення поставленого завдання. Однак вони можуть знати роль або тип людини, яку вони зазвичай просять допомогти з цими речами. Шаблон Персона дозволяє користувачам висловлювати, з чим їм потрібна допомога, не знаючи подробиць очікуваних результатів.

  • Шаблони використання LLM - Перевернута взаємодія

    Це третя стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Перевернута взаємодія

    Намір і контекст

    Ви хочете, щоб LLM ставив запитання, щоб отримати інформацію, необхідну для виконання деяких завдань. Таким чином, замість того, щоб користувач керував розмовою, ви хочете, щоб LLM керував розмовою, щоб зосередити її на досягненні конкретної мети. Наприклад, ви можете захотіти, щоб LLM провів для вас короткий тест або автоматично ставив запитання, поки не отримає достатньо інформації для створення сценарію розгортання вашої програми в певному хмарному середовищі.

    Мотивація

    Замість того, щоб користувач керував бесідою, LLM часто має знання, які може використовувати для більш точного отримання інформації від користувача. Мета шаблону Flipped Interaction полягає в тому, щоб перевернути потік взаємодії, щоб LLM ставив користувачеві запитання для досягнення бажаної мети. LLM часто може краще вибрати формат, кількість і зміст взаємодій, щоб забезпечити досягнення мети швидше, точніше та/або використовуючи знання, якими користувач може (спочатку) не володіти.

  • Шаблони використання LLM - Автоматизатор виводу

    Це друга стаття стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Автоматизатор виводу

    Намір і контекст

    Мета цього шаблону полягає в тому, щоб LLM генерував скріпт або інший артефакт автоматизації, який може автоматично виконувати будь-які кроки, які він рекомендує виконати як частину свого виводу. Мета полягає в тому, щоб зменшити ручні зусилля, необхідні для впровадження будь-яких рекомендацій від LLM.

    Мотивація

    Результатом LLM часто є послідовність кроків, які користувач повинен виконати. Наприклад, прохаючи LLM створити конфігураційний скріпт на Python, LLM може запропонувати кілька файлів які треба модифікувати та зміни, які слід застосувати до кожного файлу. Однак змушувати користувачів постійно виконувати кроки вручну, продиктовані результатом LLM, це дуже виснажливо і цей процес буде схильним до помилок.

  • Шаблони використання LLM - Шаблон створення сленгу

    Це перша стаття із серії яка описує шаблони будування запитів до LLM систем. Інші статті в серії

    Шаблон створення сленгу

    Намір і контекст

    Під час спілкування із LLM, користувач може створити запит через альтернативний діалект мови, такий як скорочені текстові позначення для графів, чи опис станів і переходів станів для кінцевої машини, чи набір команд для швидкої автоматизації тощо. Шаблон пояснює семантику цієї альтернативної мови LLM, щоб користувач міг писати майбутні запити, використовуючи цей новий сленг та її семантику.

    Мотивація

    Багато проблем, структур або інших ідей, висловлених у запиті, можуть бути виражені більш стисло, однозначно та чітко мовою, відмінною від побутової української (або іншої мови, яка використовується для взаємодії з LLM). Однак, щоб отримати результат на основі іншого професійного сленгу, LLM повинен розуміти його семантику.

  • Італійській опенсурс

    Шлях Італії до відкритого коду

    Історія використання відкритого коду в Італії серед держустанов починається із публікації змін до DECRETO-LEGGE 22 giugno 2012, n. 83. Ці зміни явно прописали можливість використовування програмного забезпечення із відкритим кодом. Ці зміни не декларували потребу використовувати саме відкритий код, але вимагали проводити оцінку ефективності використання відкритого коду у порівнянні із пропрієтарними рішеннями. Пізніше, після публкації цього закону, у листопаді 2012 Агенція Цифрової Італії (L’Agenzia per l’Italia Digitale) почала закликати усіх зацікавлених прийняти участь у процесі будування рекомендацій для виконування данних змін. На той час, в Італії вже було правило що вимагало різні держустанови ділитися між собою розробленими для них, чи куплене їм програмне забезпечення. Це правило дуже схоже до юрідичних правил ліцензування відкритого коду, де будь які зміни становляться публічними для інших.

  • Reflection on Evaluating Human Factors beyond likes of code.

    I’m very glad that more articles like this come out of academia. If you haven’t read it yet, please do, as my thoughts are based on this article.

    Personally as industry worker I suffered a lot from perceived misinterpretation of some usability and easy-of-use metrics for programming languages. Also blanket ignoring that some of my friends and coworkers have problem with understanding of some PL concepts. Also even if I totally agree with message, my perception is that message of article would pass by intended audience and things become “business as usual”. I writing this post, to probably fuel some discussion.

  • Сертіфікований перевіряльник типів

    У цьому прикладі, ми побудуємо сертифікований перевіряльник типів для простої мови виразів яка має лише 2 типа натуральні числа і логічні значення, і лише дві операції додавання і логічне І.

    Зауваження: цей приклад базується на прикладі із книги Certified Programming with Dependent Types Адама Чіліпала і прикладу із репозіторію Lean4.

  • Вартість програмного забезпечення з відкритим кодом

    Це переклад статті від Гарвадської школи бізнеса. Орігінал тут

    Зміст

  • Порівняння перевірки запозичень Rust із аналогом у C#

    Це переклад орігінальної статті із англійської. Усі дяки туди!

    Хвилинку! C# має засіб перевірки запозичень?

    Дивіться: класичний приклад безкоштовної безпеки пам’яті у Rust…

    // error[E0597]: `shortlived` does not live long enough
    
    let longlived = 12;
    let mut plonglived = &longlived;
    {
    	let shortlived = 13;
    	plonglived = &shortlived;
    }
    
    *plonglived;
    

    …портуючи на C#:

    // error CS8374: Cannot ref-assign 'shortlived' to 'plonglived' because
    // 'shortlived' has a narrower escape scope than 'plonglived'
    
    var longlived = 12;
    ref var plonglived = ref longlived;
    {
    	var shortlived = 13;
    	plonglived = ref shortlived;
    }
    
    _ = plonglived;
    
  • Learning programming by immersion

    This is translation of post in Ukrainian

    I just read article about Stephen Krashen’s theory on second language acquisition and it struck me with similarities which I see in the learning how we build software. Maybe that can be said about any skill acquisition, but given that programming languages and natural languages have some similarities I would try to speculate a bit.

  • Вивчення програмування через занурення

    Я щойно прочитав статтю про теорію Стівена Крашена щодо оволодіння другою мовою, і мене вразили паралелі, які я бачу у навчанні того, як ми будуємо програмне забезпечення. Можливо, це можна сказати про будь-яке оволодіння навичками, але, зважаючи на те, що мови програмування та природні мови мають певні схожості, я спробую трохи пофантазувати.

  • Швейцарский закон: Открытый исходный код по умолчанию

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

    Открытый исходный код и открытые правительственные данные

    Через весь интернет пролетела новость, что швейцарское правительство теперь должно выкладывать все программные продукты, под лицензиями открытого кода. Это меня очень заинтересовало, но из-за того что Швейцария не англоязычная страна, то информации о том что именно было сделано, было очень мало. А как известно, анализ законов это не о том, что публикуют в новостях. Надо читать сами законы, пусть и в переводе, и стараться самостоятельно делать выводы. Также любому разработчику конечно интересны не только законы, но и код. Где этот магический открытый исходный код. Поэтому я постарался найти достаточно информации чтобы было и что почитать и что поклацать.

  • Ашық код ретінде қабылданған: бұл швейцариялық заң.

    Бұл мақала украин тілінен аударылған. Сонымен қатар, орыс тілінде аудармасы бар.

    Ашық бастапқы код және ашық үкіметтік деректер

    Интернетте швейцариялық үкіметтің енді барлық бағдарламалық өнімдерді ашық код лицензиясымен жариялау керектігі туралы жаңалық тарады. Бұл маған өте қызықты болды, бірақ Швейцария ағылшын тілді ел болмағандықтан, нақты не істелгені туралы ақпарат өте аз болды. Белгілі болғандай, заңдардың талдауы жаңалықтарда жарияланатын нәрсе емес. Заңдардың өзін оқу керек, аудармасында болса да, және өздігінен қорытынды жасауға тырысу керек. Сонымен қатар, кез келген әзірлеушіге тек заңдар ғана емес, код та қызықты. Сол сиқырлы ашық код. Сондықтан мен оқуға да, тексеруге де жеткілікті ақпарат табуға тырыстым.

  • Tokens in different languages

    How different languages define tokens?

    One guy ask in the chat, “how should I define tokens? should I combine token information with position in file?”. That’s simple question, and coming from C#, for me answer was obviously yes. But, I was curios how other languages define different tokens.

  • Відкритий код як усталено: це швейцарський закон

    Відкритий вихідний код і відкриті урядові дані

    Через увесь інтернет пролетіла новина що швейцарський уряд тепер повинен викладати усі програмні продукти, під ліцензіями відкритого коду. Це дуже мене зацікавило, але через те що Швейцарія не англомовна країна, то інформація про те що саме було зроблено, було дуже мало. А як відомо, аналіз законів це не про те що публікують у новинах. Треба читати самі закони, хай і у перекладі, та намагатися самостійно зробити висновки. Також будь якому розробнику звісно цікаві не тільки закони, а і код. Дей цей магічний відкритий код. Тому я спробував знайти достатньо інформації щоб було і що почитати і що потицяти.

  • Безкоштовні датасети із супутників!

    Знайшов класний тред із супутниковою зйомкою. Що цікаво, вони усі безкоштовні. Тому якщо вас цікавить сучасна геодезія, або агрономія, або планування інфраструктури, думаю буде цікаво подивитися.

    Найбільш часто використовувані безкоштовні багатоспектральні супутникові зображення:

    • Sentinel 2
    • Landsat-8
  • Придумана складність у програмуванні!

    Студентам та джунам-фрілансерам присвячується.

    За останні кілька років мені кілька разів доводилося чути від розробників різного рівня досвіду, але переважно початківців:

    — Нещодавно я написав чудову, корисну, дуже складну програму

    Де ці епітети – чудовий, корисний та дуже складний стояли в один ряд і мали означати якісь виключно цінні якості цього твору. Щодо слів чудовий, корисний, то в цьому немає сумніву, але те, що слова дуже складний в цьому ряду – це, звичайно, нісенітниця.

  • MSBuid як мова програмування!

    Зі сторони виглядає що багато програмістів побоюються MSBuild і намагаются ніколи його не чіпати. Це на мою думку не дуже продуктивно. Багато цих страхів щодо MSBuild через те що у нього є свою, і досить незвична для програміста, термінологія. Я спробую показати що MSBuild це лише дінамічна мова програмування, досить чудернацька, але лише мова програмування. Можливо це полегшить читачу шлях його вивчення.

subscribe via RSS