Продолжение «"Программисты не умеют программировать"»

Просто компилирую почти пустые приложения в Delphi 7 (x86), 11.3, а также Lazarus 2.2.4 (x64). Уровень "Hello, World". Я не менял Uses, оно само туда надобавлялось. Не использовал KOL и прочие навороты.

У Lazarus просто отключал генерацию отладочной информации, у Delphi 11.3 переключал профили Debug/Release (Win32), Delphi 7 (x86) - компилил как есть, на свежеустановленной среде.

Оконное приложение:

vcl, TCaption для вывода "Hello, World". Код примерно такой (Delphi 11.3):

Delphi 11.3

Delphi 11.3

У Lazarus другой список uses:

uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

У Delphi 7 этот список такой:

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

Консольное приложение:

Lazarus

Lazarus

Delphi 11.3

Delphi 11.3

Delphi 7 - как у Lazarus + uses SysUtils.

Навороченное консольное приложение Lazarus 2.2.4. Это стандартная заготовка, я добавил только строчку № 47.

Навороченное консольное приложение Lazarus 2.2.4. Это стандартная заготовка, я добавил только строчку № 47.

По итогу накомпилировал столько приложений:

В виде таблички:

Для Delphi 7 (x86) -- вроде и Debug-версия, но там Debug-файлы генерируются отдельно, т.е. вроде и не Debug.

Решил отдельно замерять по трем компиляторам, даже Delphi 7 откопал, развитие моего комментария: #comment_306393162

Отдельно запустил C# (.NET Framework) с использованием Windows Form и получился такой код:

Все эти Form1 и label1.Text мне что-то смутно напоминают.

Все эти Form1 и label1.Text мне что-то смутно напоминают.

Андерс Хейлсберг приложил свою руку и к Delphi, и к C#. При этом C# вдохновлялась Java, а Java вдохновлялась виртуальными машинами:

в 1973 году с участием Вирта был разработан прототип виртуальной машины, исполняющей на любой платформе промежуточный «пи-код», в который предполагалось компилировать все программы

А Никлаус Вирт создал Паскаль, который лег в основу Delphi.

0
Автор поста оценил этот комментарий

По первой части приведу свой пример: уменя сейчас 7 проектов, использующих общие модули. Разные проекты используют разный набор общих модулей. Часть проектов сертифицируется, и потому должна быть возможность собрать проект в монорепозиторий в виде исходников. Решается проблема сочетанием плагинной архитектуры с менеджером пакетов, плагинная архитектура позволяет менять набор модулей без пересборки, менеджер пакетов позволяет использовать общие модули в разных проектах, и вытянуть исходники в один монорепозиторий. Никаких микросервисов, и соответствуешей потери производительности (но у нас в целом скорее desctop, сетевая часть небольшая, БД до недавнего времени простая).


А вот с похожими, но немного различающимися структурами данных в разных проектах возникает проблема. Директивы компиляции и кодогенерация ее не решают, т.к. структуры используются несколькими модулями. Даже если по сети летят json,все-равно где- это есть модуль, описывающий сериализуемые структуры, подкобчаемый на обоих сторонах сетевого соединения.


Тут у нас есть два решения. Первое - как раз опции компиляции. Те самы if defined и т.п. Аналоги есть практически в любом языке, но проблема в том, что нужно пробросить опции через менеджер пакетов. Наш менеджер пакетов (conan) это позволяет, мы буквально может указать, что для такого-то проекта нужно использовать такие-то опции. Причем в зависимости от опций можно не только dэпеоеменгые препроцессора добавлять, но подключать или отключать часть исходных файлов. И если заморочиться - скрипт сборки монорепозиторя можно доработать так, чтобы он тоже учитывал опции. Например, так мы выпилиааем тесты из сертифицируемой версии.


Но на практике опции компиляции использовать неудобно, и сложно тестировать и отлаживать. Поэтому обычно мы делаем проще: просто ослабляем типизацию в случаях, когда структуру нужно сделать конфигурируемой,. И тогда вместо структуры с именованными полями у нас используется массив пар ключ-значение, формируемый из загружаемого в рантайие файла конфигурации. Но у нас не таблицы и не БД, поэтому сделать так достаточно просто.

Хотя тоже бывают интересные моменты, когда даже такие динамические структуры дублируются или шаблонизиоуются (дженериками). Например, есть структура с десятками именованных полей, вложенная в другие структуры. Но в одном случае все поля имеют примитивный один тип, описывающий качественные характеристики, а во втором - другой тип, описывающий количественные, привет второй тип зависит от первого.


В общем, как ни крути, на мой взгляд все это зависит от конкретной экосистемы, даже не только от языка. Какой- то более-менее универсальный габлонизатор или кодогенератор возможен только для ограниченного набора позодиях ЯП.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Какой- то более-менее универсальный габлонизатор или кодогенератор возможен только для ограниченного

Пример, который я использовал, C#, web (это набросок, переменные могут отличаться):

using MyEngine;

namespace TDO.Product

{

/// <summary>

/// Сущность описания продукта

/// </summary>

public class TProduct : BaseTDO

{

<#@ include file="$Id" #>

<#@ include file="$ProductId" #>

<#@ include file="$Description" #>

<#@ include file="$Post" #>

<#@ include file="$DateCreated" #>

}

}

Файл DateCreated.inc:

/// <summary>

/// Дата создания.

/// </summary>

public DateTime DateCreated { get; set; }

И даже этот вариант слишком многословный.
Вместо того, чтобы написать так:

#u MyEngine;

#n TDO.Product;

{

#s

/// Сущность описания продукта

#s2

#pc TProduct : BaseTDO

{

#i($Id)

#i($ProductId)

#i($Description)
#i($Post)
#i($DateCreated)

}

}

И отдельно файл:

#u = "using";
#n = "namespace";

#s = "/// <summary>";
#s2 = "/// </summary>";
func #i($file_include)

{ return F"<#@ include file="$file_include" #>" }

0
Автор поста оценил этот комментарий

По моему, вы все в кучу смешали. Реальная проблема проявляется, когда в проекте есть куча модулей на разных языках, использующие схожие структуры данных, и, иногда, алгоритмы. Тут действительно возникает желание написать кодогенератор. В этом плане llvm скорее способствует идее переписать все на одном языке, т.к. если все языки компилируются в одно промежуточное представление, значит они имеют одинаковые потенциальные целевые платформы.



Что касается grud - в целом это скорее все же про дженерики. Но очень зависит от языка, возможностей дженериков и рефлексии. Самое универсальное решение - создать одну структуру, описывающую таблицу в виде набора статических полей (от них нужны имена и типы, а не значения), а конкретные поля выбираем при выполнении запроса, объединяя в кортеж. Передали в запрос поля 1,4,7,25 - получили в ответ кортеж из четырех значений в том же порядке. Но на деле, конечно, есть много нюансов. Мне пока только предстоит в это вникнуть.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

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

Есть другой вариант -- когда реализуются 3 разных проекта. Вообще любое количество >=2.

И часть кода -- это буквально копипаста между проектами. И нельзя допускать, чтобы код для заказчика А уходил к заказчику Б.

Т.е. изначально все на одном языке. Например, на Python(Django). Нужно реализовать для двух частников и одного гос.заказчика сайты. Каркас совпадает, но в мелочах различия. Какие-то модули нужные одному частнику, какие-то другому, что-то для гос.заказчика.


Или ситуация у яндекса, когда куча проектов использует один и тот же код. Они, кстати, предложили вариант с монорепозиторием, т.е. все проекты хранятся в одном репозитории и можно часть библиотек сделать общими.


Еще читал про вариант гибрида монолита и микросервиса. Т.е. приложение - типичный монолит. Но у этого приложения есть конфиг-файл, который разъясняет позицию вплоть до того, что приложение должно вести себя как микросервис. Соответственно, у монолита работают только те части, которые отвечают за определенный функционал и пересылают все в JSON другим копиям этого приложения, которые ведут себя как другие микросервисы.

Преимущество - в производительности. Т.к. есть два адаптера - внутренняя и внешняя передача данных. Если у монолита активировано два модуля, то эти модули общаются между собой по внутренней шине. Если нужно общаться с другими модулями, то вперед конвертировать в JSON и другие форматы.

Соответственно, у монолита сразу минус к дублированию кода между микросервисами, т.к. одинаковый код отвечает за работу с HTTP и JSON. И DTO не нужно раскидывать между микросервисами.


В Delphi есть конструкции типа:

{$IF Defined(MY_DEFINE) and (LibVersion > 2.0) }

Writeln(1);

{$ELSE}

Writeln(2);

{$IFEND}

Т.е. можно даже на этапе компиляции собирать вообще разные приложения из одного монолита просто задавая разные директивы компилятора.


Проблема компиляции с помощью директив - я не получаю исходный код, который будет разбит по проектам. Так можно было бы сделать одно приложение, которое автоматически нарежется для разных заказчиков.
И когда я беру 4й заказ - я должен лишь добавить diff к этому универсалу, отключив ненужные модули. И все, получаю исходники и нужные алгоритмы.

Эту идею я еще могу решить с помощью кодогенератора. Но возникает и обратная проблема. Если мне пришлют мой же код, но в котором сделали правки, то все, я не смогу отследить изменения и вернуть обратно в режим главного приложения.
Т.е. нужно писать еще и обратный кодогенератор, который сравнит с оригинальным приложением и сформирует два файла:
1) изначально примененный конфиг (я его не передаю заказчику и, теоретически, могу потерять). Или я свое глобальное приложение переделал и теперь нужен "изначальный конфиг" относительно переделанного приложения.
2) diff с моим изначальным проектом. Т.е. какие изменения были применены к приложению.

Это попахивает еще и необходимостью писать свою систему управлению версиями кода.


Что касается grud - в целом это скорее все же про дженерики

я про DTO, а не про контроллеры. Т.е. необходимо как раз генерировать ту самую описывающую таблицу в виде набора статических полей. Если таблиц в одном проекте 10, в другом 12, в третьем 15, то всего 37 таблиц. А поле ID вообще повторяется в каждой таблице, как и часть полей между проектами. Например, поле ID для каждой таблицы нужно копипастить.
А DTO-списки - это отдельные таблицы на CRUD. Т.е. createDTO (тут нет поля ID, какие поля нужны для создания записи), updateDTO (поля для изменения записи), readDTO (что читаем), deleteDTO (что удаляем). И получаем, что на три проекта 37 таблиц + 3*37 DTO = 148 раза встречается поле ID. А можно сделать readDTO в зависимости от роли пользователя - гость, пользователь или администратор. Это еще х3. И получаем 37 таблиц + 2*37 DTO + 3*readDTO = 222 раза скопировать поле "ID".


Я получал рекомендацию от скилованных прогеров писать это вручную или отдать джуну, что снова делается вручную, просто другим человеком.


Соответственно, подумываю написать генератор DTO. Т.е. сделать базу с разными возможными названиями полей. А потом в визуальном редакторе через Drag&Drop комплектовать базовую таблицу и списки DTO под нее -- create, read, update, delete. С возможными вариантами по ролям, кому что можно.
Я не знаю конструкции в OOP, которая бы описывала DTO по принципу array of boolean. Т.е. расставив галочки мне формируется соответствующая DTOшка.


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


Кстати, видимо именно поэтому программисты надеются на условный ChatGPT, чтобы он забрал часть вот такой рутины.

показать ответы
0
Автор поста оценил этот комментарий

Действительно. Дельфи хотя бы компилируется, не то что недо-С или Си-решетка.... гыг.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

я до этого писал на Python.


И вообще, меняю инструменты в зависимости от задач. Есть опыт написания и на PHP, и на Python, и Delphi/Lazarus/FreePascal/TurboPascal, и на ассемблере, и на других языках.


Но срачи какой язык лучше интереснее аргументацией, где какая технология есть. Жаль, что не все умеют в аргументацию...

0
Автор поста оценил этот комментарий

Спасибо за подробную подборку с цитатами. Но есть нюансы.


Net уже не один, а скоро не два десятка лет в строю. Знаю, что в 2004 уже разрабатывали коллеги на ней. И как раз брал фреймворк свое начало с mono.

Это только net core в 2016м отделилось.


Но особо спорить не буду. С ней тесно не работал, только ради практического интереса с ней сталкивался.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

И как раз брал фреймворк свое начало с mono

Специально открыл историю различных версий. Нет, mono не первый.


Из блога разработчика mono:

Что касается Mono, события происходили примерно следующим образом.
Как только в декабре 2000 г. вышла документация .NET, я заинтересовался этой технологией и начал изучать её, как и все, с интерпретатора байт-кода

При этом MS:

Первоначальный .NET Framework от Microsoft появился в конце 90-х

https://habr.com/ru/companies/clrium/articles/466811/


Т.е. MS с Net Framework и Mono -- это две параллельные ветки под разные платформы и автор Mono не мог основать NET, т.к. ждал документацию от ECMA:

Примерно в это же время Сэм Руби пытался убедить членов комитета ECMA опубликовать описание формата бинарного файла, что не входило в их планы

И ваш аргумент:

Знаю, что в 2004 уже разрабатывали коллеги на ней

Логично, ведь в 2004 уже многое было. И NET Framework, вышедший в 2002, т.е. "спустя 2 года после выхода ваши коллеги стали разрабатывать на этой технологии"

Иллюстрация к комментарию
0
Автор поста оценил этот комментарий

LLVM - это не виртуальная машина времени выполнения, это виртуальная машина времени компиляции. Виртуализируется код промежуточного представления, который уже транслируется и оптимизируется под целевую платформу. Целевой платформой может быть другой байт-код, или конечный машинный код, но в любом случае код промежуточного представления в релиз обычно не попадает и никакой избыточности создавать не должен. А если и попадает - это компромис, в таком случае любой другой байт-код либо будет не лучше, либо конкретная цепочка инструментов не оптимизирована и заслуживает порицания.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Немного не в тему

Виртуализируется код промежуточного представления, который уже транслируется и оптимизируется под целевую платформу

разные заказчики требуют код на разных языках. Условно, мне приходилось писать на Delphi, C#, Python и т.д. По факту я часто писал один и тот же алгоритм на разных языках. Или даже похожий код под разные типы данных. Дженерики не помогут, т.к. есть небольшие различия в нюансах.


Так и хочется аналог LLVM в другую сторону, чтобы извлекать общие алгоритмы и именно их переносить между языками или быстро модифицировать для конкретных задач, не переписывая все с нуля.


Какое-нибудь мета-программирование, кодогенерация и т.д., но пока не находил ничего интересного. Видел шаблонизатор T4 для C#, но он оказался убогим и костыле-зависимым, т.к. не поддерживает переменные. Сам C# не умеет в банальный include. А в официальной справке по T4 предлагают переменные записывать в файл настроек проекта, что только подчеркивает маразм, т.к. шаблон становится непереносимым, да и редактировать файл настроек проекта выглядит нереальным костылем, он прибит гвоздями к Visual Studio.


Если что, я хотел создать шаблоны кода, чтобы генерировать по битовым картам нужное поведение.


Например, есть шаблон с перечислением 50 базовых полей.

И я отмечаю, что мне нужны поля №3,14,25,26,27,28 и т.д. И на базе этого генерится набор DTO - для стандартного CRUD и для всякого нестандартного списка полей. Так, я передумал, поле №14 мне не нужно и оно удаляется. Хотя в шаблоне оно есть и в другом проекте пригодится.


Помню еще предлагал одному разрабу сделать шаблонизированную справку. Но то обсуждение не дожило до сегодня, т.к. прошло примерно 12 лет...

показать ответы
0
Автор поста оценил этот комментарий

До некоторого момента можно было ставить. Это было во времена, когда дельфя использовала. Net фреймворк.

Сейчас похоже и C# под новомодные фичи будут переделывать. Ведь сам же. Net из mono выкрисализовался. А это линуксовая приблуда.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Net из mono выкрисализовался

Разве? Там же две ветки - net framework и net core.

net core вроде как из mono пошел, а mono из попытки перенести net framework в линуксы, т.к. до этого в линуксах net-приложения невозможно было запускать, они были исключительно виндовыми.


.NET Framework — программная платформа, выпущенная компанией Microsoft в 2002 году.

Mono - первый выпуск 30 июня 2004

После заключения Microsoft договорённости с компанией Novell(2012) платформа Mono была официально признана реализацией .NET на Unix-подобных операционных системах (Linux, macOS и других).

С некоторыми ограничениями, т.к. не все компоненты были разрешены.

В связи с этим вице-президент Novell Мигель де Икаса объявил, что с этого момента проект Mono будет разбит на две ветки:

- ветка, занимающаяся реализацией ECMA-стандартов и попадающая под действие Обещания — свободная от претензий Microsoft,

- ветка, реализующая свободные версии патентованных технологий ASP.NET, ADO.NET, Winforms и других.

.NET (ранее известна как .NET Core) — преемник .NET Framework, является открытой и кроссплатформенной реализацией .NET Framework от корпорации Microsoft.

У net core первая версия выпущена в 2016 году. И у них LTS-версии всего на 3 года. Т.е. редкое говнище.

.NET 6 (LTS) 8 ноября 2021 года - 12 ноября 2024 года

Я знаю проекты, которые стабильно работают по 10 лет и идти их портировать каждые три года -- это маразм. Т.е. такой подход -- это буквально кормить кучу программистов, которые будут переписывать и тестировать работающий код. Походу, пытаются побороть безработицу в США такими вот методами...

показать ответы

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества