По причинам несоответствия этого утверждения объективной реальности, или потому, что звучит неприятно?
Потому что это характеристика личных качеств людей, работающих в парадигме ООП. Кстати, в принципе некорректная, вы никак не можете говорить про всех. Равно как и пример про кошечек и собачек. Вам откуда знать, по каким книгам я учился?
я вообще так-то матершинник, вырос на двач-adjacent-культуре
Если в тексте хуй пизда и джигурда, я тоже не буду оскорбляться. Хотя про джигурду я чот перегнул...
Мы начали с того, что 5к строк проекта - это маленький проект. Собственно, на этом и остановились.
То, что ваш проект на 5к строк хоть немного близок по объёму к моему на 50к - это, мягко говоря, неправда. А в контексте управления сложностью объём проекта - это ключевой параметр. Без объёма никакого управления сложностью и не нужно. Крохотные скрипты на 500 строк вполне обходятся и без ORM и без ООП и даже без статической типизации. Это всё инструменты, которые начинают работать позже.
Я вот читаю весь этот снисходительный пафос и не пойму... А где решение в 10 раз короче? То, что я написал - работает.
То, что там именно сообщения вылавливаются, без типов ошибки, так извините, это я так понял. Так объяснено было. Можно и с типом ошибки отлавливать, вообще никаких вопросов. Вместо string будет Exception. И что?
Я напомню, этот пример специально для haskell. У вас loadComments использует готовые структуры языка/библиотек и выдаёт данные, подогнанные к условиям задачи.
В ООП вообще не принято думать в терминах действий
Вот так говорить вообще не надо. Это в крайней степени некорректно. И говорит разве что о вас и вашем восприятии.
Делать выводы по оторванному от реальности куску кода - это какая-то специальная олимпиада. Нет, серьёзно. Это действительно похоже на какую-то олимпиаду, когда люди соревнуются в написании куска кода по условиям задачи.
Читать Func<int, List<int>, string> тем более легче, чем Int → [Int] → String — заодно глаза тренируются скобочки
Это тоже некрасивый приём. В моём коде таких конструкций нет. Вы её сами продумали.
Я вижу, что чьё-то самолюбие задето. Настолько, что потребовалось вот как-то доказать превосходство хаскеля над шарпом. Самоутвердиться так сказать. Причём не самыми адекватными способами.
книги по ООП учат разделять кошечек, собачек, квадратики и прямоугольнички
Вот это мне вообще не понравилось. Прямо какой-то дон в белом плаще смотрит, как там крестьяне палкой землю ковыряют.
Я сейчас вот что сделаю. Просто сверну разговор и на этом закончим. У меня нет никакого желания дальше его продолжать. Уж очень токсично получается.
Я вернусь в свой несовершенный мир, где есть гуй авалонии, есть разор пейджес и буду дальше писать свой несовершенный продукт. А вы пойдёте своим путём и будете писать свои небольшие, но совершенные проекты. Идёт?
Это чтобы потом вместо того, чтоб просто посмотреть на тип функции, ходить спрашивать «а что функция кидает?», как вы уже сделали выше?
Современные IDE показывают, какие эксепшены может кинуть та или иная функция. В каких-то языках в комментах пишут. В java принудительно нужно указывать в сигнатуре, какие эксепшены можешь кинуть.
А тут вам в условии дали фору: сигнатуру можете выбрать как вам удобнее.
Окей, я выбираю сигнатуру LoadComment(ref Node node). Тогда всё сведётся к одному рекурсивному вызову.
Окей, хорошо. Пусть там на входе айди, пусть на выходе коммент. Иногда эксепшен. Перехватываем только NotFound, оставльные прокидываем наверх. Допустим. Хотя нет. Тогда смысла нет сохранять текст ошибки. Будем все ловить.
class Node
{
public int id;
public string? comment;
public string? error;
public List<Node> children = new();
void LoadComments(Node node, Func<int, string> loadComment)
{
try { node.comment = loadComment(node.id); }
catch (Exception ex) { node.error = ex.Message; }
foreach (var child in node.children)
LoadComments(child, loadComment);
}
}
Вот собственно структура с рекурсивным методом загрузки
Всмысле перевести? Мне функцию дали. По условию. Где сигнатура?
Если по своему, то во-первых, возвращение NetworkError - чушь собачья. При живых эксепшенах.
Во-вторых, запрос коммента по сети по одному - чушь собачья. В реальных системах так не делается. Либо по айди объекта выгребают пачкой из базы, либо по "IN" в случае если нужно несколько объектов, где каждому нужен например последний коммент.
В третьих, эксепшены всегда разделяются на критичные и некритичные. Если критичный, то дальше смысла нет. Например ошибка кредов - вот зачем дальше выбирать эти комменты? Такие пробрасываются наверх, а не отдаются.
Как выражается «либо» в шарпе идиоматически
Никак. Это не хаскель.
И шарп статически типизированный. Там нельзя инт поменять на коммент.
Вы по кругу просто ходите, что ли? Сигнатуру я уже тоже выше писал:
Я на шарпе пишу, нахер мне сигнатура хаскеля?
Не понял. Кто запретил?
У шарпа есть тип возвращаемого значения. Входит в сигнатуру функции. Там ещё входные параметры, но допустим на входе int id. Какой тип возвращаемого значения?
И скажите, какой апи для получения комментов. И для вывода ошибок. Что это будет, вьюмодель, джсон или ещё что?
Если это какой-то бекенд, то давайте сначала ПОЛНЫЙ текст на хаскеле обработки апи. Вместе с загрузкой дерева, вместе с отправкой комментов. Вместе с сериализацией. А потом будем сравнивать именно полный текст.
У вас полная свобода, делайте как вам удобнее.
Я так и сделал. В чём проблема? Вы даже не потрудились сказать, где может ошибка возникнуть.
Всё ваше недовольство - это то, что сделано не по-вашему. Так по вашему и не надо. Надо, чтобы работало.
У меня есть, допустим, репозиторий, который вам очень сложно будет повторить. Потому что там нет места функциональщине. Там выключен Нейгл и включено на максимум байтоёбство. И даже если получится, в 1800 строк вы на хаскеле ну никак не уложитесь. Это не его.
Да, ещё раз скажу. 5000 строк - это даже не маленький проект. Это крохотный. Не надо говорить, что хаскель компактный. Это не так.
Мы с вами не сработаемся. Спасибо за уделённое время, можете не перезванивать.
Если серьёзно, то да, бывает что нужно так. Только вы забываете про одну мааааленькую деталь. Когда я работаю над проектом, я работаю на шарпе. И у меня нет деревьев хаскеля. У меня всё другое. И просить сделать c# метод по хаскель дереву - в высшей степени некорректно.
Выкинуть половину условия задачи и говорить, что сделали это специально
У вас условие притянуто за уши к функциональщине. Ошибки так не ловятся. Сове больно и обидно. Вы хотите что-то поймать, но сами не знаете, что и зачем.
Если надо задачку решить шарпом - не сомневайтесь, я её смогу решить. Надо насобирать либо коммент, либо почему айди коммента нет? Да не вопрос. Ещё пара строк. Всё равно меньше по строкам будет, чем у вас.
Где вы этот запрос делаете, кстати — не видно.
А давайте теперь поговорим о том, что у вас тоже нихрена не видно. Ни куда ошибки уходят, ни как они парсятся, ни как идёт запрос в базе. Тоже очень дохрена условностей.
У меня стандартный апи к Entity Framework, если что. Довольно узнаваемый.
Итого ошибки вы не обрабатываете, древообразную структуру комментариев потеряли, и, судя по форме запроса, потеряли даже порядок комментариев.
Можете всё-таки написать одну функцию целиком, которая это всё делает?
Ничего подобного. Структура на месте, ошибки наверху ловятся. Функция ради функции - ну определитесь с границами. Я не пойму, чего вы хотите. Доказать, что хаскель компактнее шарпа? Ну это, мягко говоря не так.
И я вам скажу, что ваш код нихрена не делает. Вы не разворачиваете дерево, вы не парсите ошибки, вы не запрашиваете комменты. А почему? Потому что я обвязки этого кода не вижу.
неверно, потому что код, который я вам покажу, когда вы всё-таки сделаете плюс-минус что-то, соответствующее предложенной задачке, будет иметь меньше строк, чем у вас уже написано.
Код делает больше, чем вы просили. Просто вы не можете его вставить в свою любимую парадигму. Он там работать не будет.
Проблема большого проекта зависит от большого проекта. Где-то это производительность, где-то надежность, где-то скорость разработки. Пользователю плевать сколько когнитивных усилий Вам нужно приложить чтобы добавить фичу или решить баг, это исключительно Ваша проблема.
Проблема большого проекта - в том, что он большой. Его тупо трудно удержать в голове и всё сложнее править. Пользователя в вопросах архитектуры никто спрашивать не будет. То, что это моя проблема - я хорошо знаю без ваших подсказок.
Собственно, я эту проблему и решаю. Для себя. И для меня хорошо себя зарекомендовали инструменты ООП, которыми я умею пользоваться и они мне приносят пользу.
ОРМ это костыль
Не костыль, а инструмент. Для связывания, да. Очень много разрабов считают, что в ООП работать проще, чем с плоскими данными. И я к ним тоже отношусь. И если вы предпочитаете кидаться чистым sql и выгребать каждый раз свой набор полей, то у меня в ORM синтаксис намного короче и я оперирую объектами, а не полями, что уже на одну абстракцию выше. Кроме того, у меня есть возможность одним кликом узнать, в каких частях проекта используется вот это поле.
За деревьями леса не видно?
А давайте нормально разговаривать? Без обвинений в недальновидности
Преимущество парадигмы в том что без нее не будет работать подходы основанные на этой парадигме?
А кто мне только что ставил в упрёк, что современные системы - это анемичная модель, а не ООП?
Окей, моё любимое упражнение. У вас есть дерево с интами и функция, которая по инту-айдишнику загружает по сети, скажем, комментарий с этим айди (ну или возвращает ошибку). Можете написать код на шарпе, который проходит по дереву, загружает эти комментарии, и либо собирает все ошибки (если была хотя бы одна), либо отдаёт дерево комментариев?
Оу. У нас хвостовая рекурсия и discrimination unit, судя по всему. Ну чтож, давайте сравнивать шарп с хаскелем на поле хаскеля. Я точно также сделаю, выборку айдишников отдельно, запрос отдельно.
Можно и одной строкой развернуть дерево. Вроде этого:
Просто чтобы можно было с любого уровня разобрать дерево.
Потом запрос:
var comments = context.Comments.Where(
c => node.AllChildIds.Contains(c.id))
Может чуть-чуть больше букв. Но в шарпе даже меньше строк. И для меня синтаксис хаскеля выглядит типичной ФП-сплющенной чёрной магией, где за смысл отвечают знаки препинания, а не слова. Это как раз то, что я не люблю в ФП. То, что мне не понравилось в котлине. То, за что я ненавижу регулярки. Оно на мой вкус не читается вообще. В шарпе - читается. В хаскеле - нет.
И да, я специально не стал отлавливать ошибки. Я знаю, что такое DU. Но ошибки надо понимать, где могут возникнуть. У меня запрос комментов идёт одним селектом в "IN" синтаксисе, он либо весь сработает, либо вообще не сработает. В дереве ошибок быть не может.
В шарпе я постоянно пользуюсь такими вещами, как Sum(i => vec[i]), Select/SelectMany, цепочки функций и другие элементы ФП. Так что в данном случае шарп с хаскелем будет 1:1. А вот специфичные для шарпа ситуации могут быть совсем не в пользу хаскеля. C# - очень насыщенный язык с огромным количеством синтаксического сахара, с ним мало кто может тягаться по выразительности и краткости. Не только лишь все это могут.
На C++ — маленький. На хаскеле — средний.
Мне это напоминает заявление представителя эппла, что их 8гб это как 16гб на "обычных" компьютерах. Настолько же голословное. У крестов есть мощная система шаблонов и если по шаблонам упороться, можно оставить любой фп язык позади без вариантов вообще. Я имею в виду по плотности смысла на строку кода.
Это хорошо, когда разработчики придерживаются старого правила "писать компилятор на компилируемом языке". Это как старая добрая традиция ставить архитектора под мост во время приёмки. Только это скорее необходимый минимум, proof-of-concept, чем пример реального проекта.
например, был у меня один проект на хаскеле, пять тыщ строк, написан в одиночку по большому счёту. Если бы я его переписал на C++, то там было бы по моим оценкам примерно на порядок больше
И что, это хорошо? Я могу сказать, в каком случае это хорошо. Когда в одном языке меньше бойлерплейт конструкций, чем в другом. А когда количество строчек сокращается за счёт повышения когнитивного порога восприятия кода - это плохо. Очень плохо.
Считать ли это «большим» [для одного разработчика] проектом? 50 тыщ строк
Во-первых это совершенно условные 50 тыс строк, которые вы вывели исходя из придуманного коэффициента. Вот передо мной проект ormfactory, который я пишу в одно лицо. Там 36kloc самого аппа, 6kloc тестов, 5 сайта, и ещё оракловый коннектор с бриджем ещё 5к. Питоногенераторы, батнички и доки я даже не считаю. Там ещё тулзы вспомогательные есть. 50 должно набраться. А это C#, который мультипарадигменный, и функциональщину там я не стесняюсь использовать, так что коэффициент 10 тут будет точно мимо.
Когда я писал erp-систему в течении 12 лет (не один), то там набралось более 200kloc. Вот это средне-большой проект. 50 - средний. А 5к - маленький, как ни крути.
Потому что это характеристика личных качеств людей, работающих в парадигме ООП. Кстати, в принципе некорректная, вы никак не можете говорить про всех. Равно как и пример про кошечек и собачек. Вам откуда знать, по каким книгам я учился?
Если в тексте хуй пизда и джигурда, я тоже не буду оскорбляться. Хотя про джигурду я чот перегнул...
Мы начали с того, что 5к строк проекта - это маленький проект. Собственно, на этом и остановились.
То, что ваш проект на 5к строк хоть немного близок по объёму к моему на 50к - это, мягко говоря, неправда. А в контексте управления сложностью объём проекта - это ключевой параметр. Без объёма никакого управления сложностью и не нужно. Крохотные скрипты на 500 строк вполне обходятся и без ORM и без ООП и даже без статической типизации. Это всё инструменты, которые начинают работать позже.
Я вот читаю весь этот снисходительный пафос и не пойму... А где решение в 10 раз короче? То, что я написал - работает.
То, что там именно сообщения вылавливаются, без типов ошибки, так извините, это я так понял. Так объяснено было. Можно и с типом ошибки отлавливать, вообще никаких вопросов. Вместо string будет Exception. И что?
Я напомню, этот пример специально для haskell. У вас loadComments использует готовые структуры языка/библиотек и выдаёт данные, подогнанные к условиям задачи.
Вот так говорить вообще не надо. Это в крайней степени некорректно. И говорит разве что о вас и вашем восприятии.
Делать выводы по оторванному от реальности куску кода - это какая-то специальная олимпиада. Нет, серьёзно. Это действительно похоже на какую-то олимпиаду, когда люди соревнуются в написании куска кода по условиям задачи.
Это тоже некрасивый приём. В моём коде таких конструкций нет. Вы её сами продумали.
Я вижу, что чьё-то самолюбие задето. Настолько, что потребовалось вот как-то доказать превосходство хаскеля над шарпом. Самоутвердиться так сказать. Причём не самыми адекватными способами.
Вот это мне вообще не понравилось. Прямо какой-то дон в белом плаще смотрит, как там крестьяне палкой землю ковыряют.
Я сейчас вот что сделаю. Просто сверну разговор и на этом закончим. У меня нет никакого желания дальше его продолжать. Уж очень токсично получается.
Я вернусь в свой несовершенный мир, где есть гуй авалонии, есть разор пейджес и буду дальше писать свой несовершенный продукт. А вы пойдёте своим путём и будете писать свои небольшие, но совершенные проекты. Идёт?
Современные IDE показывают, какие эксепшены может кинуть та или иная функция. В каких-то языках в комментах пишут. В java принудительно нужно указывать в сигнатуре, какие эксепшены можешь кинуть.
Окей, я выбираю сигнатуру LoadComment(ref Node node). Тогда всё сведётся к одному рекурсивному вызову.
Окей, хорошо. Пусть там на входе айди, пусть на выходе коммент. Иногда эксепшен. Перехватываем только NotFound, оставльные прокидываем наверх. Допустим. Хотя нет. Тогда смысла нет сохранять текст ошибки. Будем все ловить.
Вот собственно структура с рекурсивным методом загрузки
Всмысле перевести? Мне функцию дали. По условию. Где сигнатура?
Если по своему, то во-первых, возвращение NetworkError - чушь собачья. При живых эксепшенах.
Во-вторых, запрос коммента по сети по одному - чушь собачья. В реальных системах так не делается. Либо по айди объекта выгребают пачкой из базы, либо по "IN" в случае если нужно несколько объектов, где каждому нужен например последний коммент.
В третьих, эксепшены всегда разделяются на критичные и некритичные. Если критичный, то дальше смысла нет. Например ошибка кредов - вот зачем дальше выбирать эти комменты? Такие пробрасываются наверх, а не отдаются.
Никак. Это не хаскель.
И шарп статически типизированный. Там нельзя инт поменять на коммент.
Я на шарпе пишу, нахер мне сигнатура хаскеля?
У шарпа есть тип возвращаемого значения. Входит в сигнатуру функции. Там ещё входные параметры, но допустим на входе int id. Какой тип возвращаемого значения?
Сигнатура какая у функции?
Чтобы два раза не вставать. Int нельзя заменить на строку. И на Comment тоже.
Неправильно. Давайте ещё раз
Полный формат функции. Что принимает, что выдаёт, чем кидается.
Выходной формат, который от меня требуется. В каком виде это передаётся дальше.
Я очень рад, но проект на 5к строк нельзя назвать большим. И средне-большим. И даже средним. Никак.
Нет-нет. Шарпа. Мне же надо на шарпе сделать.
И скажите, какой апи для получения комментов. И для вывода ошибок. Что это будет, вьюмодель, джсон или ещё что?
Если это какой-то бекенд, то давайте сначала ПОЛНЫЙ текст на хаскеле обработки апи. Вместе с загрузкой дерева, вместе с отправкой комментов. Вместе с сериализацией. А потом будем сравнивать именно полный текст.
Я так и сделал. В чём проблема? Вы даже не потрудились сказать, где может ошибка возникнуть.
Всё ваше недовольство - это то, что сделано не по-вашему. Так по вашему и не надо. Надо, чтобы работало.
У меня есть, допустим, репозиторий, который вам очень сложно будет повторить. Потому что там нет места функциональщине. Там выключен Нейгл и включено на максимум байтоёбство. И даже если получится, в 1800 строк вы на хаскеле ну никак не уложитесь. Это не его.
Да, ещё раз скажу. 5000 строк - это даже не маленький проект. Это крохотный. Не надо говорить, что хаскель компактный. Это не так.
Мы с вами не сработаемся. Спасибо за уделённое время, можете не перезванивать.
Если серьёзно, то да, бывает что нужно так. Только вы забываете про одну мааааленькую деталь. Когда я работаю над проектом, я работаю на шарпе. И у меня нет деревьев хаскеля. У меня всё другое. И просить сделать c# метод по хаскель дереву - в высшей степени некорректно.
Давайте структуру шарпа, я сделаю.
А нахрена же вы комментарии по одному грузите? За это даже на собеседованиях на джуна руки отрывают.
У вас условие притянуто за уши к функциональщине. Ошибки так не ловятся. Сове больно и обидно. Вы хотите что-то поймать, но сами не знаете, что и зачем.
Если надо задачку решить шарпом - не сомневайтесь, я её смогу решить. Надо насобирать либо коммент, либо почему айди коммента нет? Да не вопрос. Ещё пара строк. Всё равно меньше по строкам будет, чем у вас.
А давайте теперь поговорим о том, что у вас тоже нихрена не видно. Ни куда ошибки уходят, ни как они парсятся, ни как идёт запрос в базе. Тоже очень дохрена условностей.
У меня стандартный апи к Entity Framework, если что. Довольно узнаваемый.
Ничего подобного. Структура на месте, ошибки наверху ловятся. Функция ради функции - ну определитесь с границами. Я не пойму, чего вы хотите. Доказать, что хаскель компактнее шарпа? Ну это, мягко говоря не так.
И я вам скажу, что ваш код нихрена не делает. Вы не разворачиваете дерево, вы не парсите ошибки, вы не запрашиваете комменты. А почему? Потому что я обвязки этого кода не вижу.
Код делает больше, чем вы просили. Просто вы не можете его вставить в свою любимую парадигму. Он там работать не будет.
Оно не нужно на практике. Если у вас в проекте тысячи крудов и ни одной логики - вы в дурке. Бегите.
Не может.
Вуаля. ООП как раз и предлагает модульность. На уровне классов.
Как ничего не является волшебной таблеткой.
Базы данных мы тоже сами себе придумали.
Это как вообще?
Всмысле? А профит фаундеру? Ну перегорят и перегорят, несите следующего.
Проблема большого проекта - в том, что он большой. Его тупо трудно удержать в голове и всё сложнее править. Пользователя в вопросах архитектуры никто спрашивать не будет. То, что это моя проблема - я хорошо знаю без ваших подсказок.
Собственно, я эту проблему и решаю. Для себя. И для меня хорошо себя зарекомендовали инструменты ООП, которыми я умею пользоваться и они мне приносят пользу.
Не костыль, а инструмент. Для связывания, да. Очень много разрабов считают, что в ООП работать проще, чем с плоскими данными. И я к ним тоже отношусь. И если вы предпочитаете кидаться чистым sql и выгребать каждый раз свой набор полей, то у меня в ORM синтаксис намного короче и я оперирую объектами, а не полями, что уже на одну абстракцию выше. Кроме того, у меня есть возможность одним кликом узнать, в каких частях проекта используется вот это поле.
А давайте нормально разговаривать? Без обвинений в недальновидности
А кто мне только что ставил в упрёк, что современные системы - это анемичная модель, а не ООП?
Оу. У нас хвостовая рекурсия и discrimination unit, судя по всему. Ну чтож, давайте сравнивать шарп с хаскелем на поле хаскеля. Я точно также сделаю, выборку айдишников отдельно, запрос отдельно.
Можно и одной строкой развернуть дерево. Вроде этого:
Только я сделаю рекурсивную проперть в ноде вроде такой:
Просто чтобы можно было с любого уровня разобрать дерево.
Потом запрос:
Может чуть-чуть больше букв. Но в шарпе даже меньше строк. И для меня синтаксис хаскеля выглядит типичной ФП-сплющенной чёрной магией, где за смысл отвечают знаки препинания, а не слова. Это как раз то, что я не люблю в ФП. То, что мне не понравилось в котлине. То, за что я ненавижу регулярки. Оно на мой вкус не читается вообще. В шарпе - читается. В хаскеле - нет.
И да, я специально не стал отлавливать ошибки. Я знаю, что такое DU. Но ошибки надо понимать, где могут возникнуть. У меня запрос комментов идёт одним селектом в "IN" синтаксисе, он либо весь сработает, либо вообще не сработает. В дереве ошибок быть не может.
В шарпе я постоянно пользуюсь такими вещами, как Sum(i => vec[i]), Select/SelectMany, цепочки функций и другие элементы ФП. Так что в данном случае шарп с хаскелем будет 1:1. А вот специфичные для шарпа ситуации могут быть совсем не в пользу хаскеля. C# - очень насыщенный язык с огромным количеством синтаксического сахара, с ним мало кто может тягаться по выразительности и краткости. Не только лишь все это могут.
Мне это напоминает заявление представителя эппла, что их 8гб это как 16гб на "обычных" компьютерах. Настолько же голословное. У крестов есть мощная система шаблонов и если по шаблонам упороться, можно оставить любой фп язык позади без вариантов вообще. Я имею в виду по плотности смысла на строку кода.
Это хорошо, когда разработчики придерживаются старого правила "писать компилятор на компилируемом языке". Это как старая добрая традиция ставить архитектора под мост во время приёмки. Только это скорее необходимый минимум, proof-of-concept, чем пример реального проекта.
И что, это хорошо? Я могу сказать, в каком случае это хорошо. Когда в одном языке меньше бойлерплейт конструкций, чем в другом. А когда количество строчек сокращается за счёт повышения когнитивного порога восприятия кода - это плохо. Очень плохо.
Во-первых это совершенно условные 50 тыс строк, которые вы вывели исходя из придуманного коэффициента. Вот передо мной проект ormfactory, который я пишу в одно лицо. Там 36kloc самого аппа, 6kloc тестов, 5 сайта, и ещё оракловый коннектор с бриджем ещё 5к. Питоногенераторы, батнички и доки я даже не считаю. Там ещё тулзы вспомогательные есть. 50 должно набраться. А это C#, который мультипарадигменный, и функциональщину там я не стесняюсь использовать, так что коэффициент 10 тут будет точно мимо.
Когда я писал erp-систему в течении 12 лет (не один), то там набралось более 200kloc. Вот это средне-большой проект. 50 - средний. А 5к - маленький, как ни крути.
Нет, не странно. Люди делают инкапсуляцию и наследования так, как могут. При отсутствии нормальных конструкций в самом языке.