Классы как абстрактные типы данных с элементами «переменная», «свойство», «функция», «процедура»; Интерфейсы как абстрактные классы без элементов состояния («переменная») и без привязки к реализации методов (свойств, процедур, функций) при определении; Имплементация (реализация) интерфейсов классами;
— одиночное открытое наследование; Области видимости «внутренняя» (private), «экспорт» (public), «защищенная» (protected); Статические элементы классов (общие для всех экземпляров класса); Замещение (переопределение реализации) методов при наследовании – «виртуальные методы, свойства»; Сокрытие (затенение) обычных (не замещаемых) элементов при наследовании; Перегрузка процедур и функций по количеству и типам данных аргументов; Конструкторы класса; Деструктор класса; Слабые ссылки; Делегаты.
Компонента представленная в этой статье привносит в 1С возможность определять сущности вида:
Класс Машинка
Функция ДайКоличествоКолес(), Абстрактная
КонецКласса
Класс МашинкаЛегковая Наследует Машинка
Функция ДайКоличествоКолес(), Замещает
КонецКласса
Класс МашинкаБТР87
Внутр:
Перем м_колКолес;
Экспорт:
Функция ДайКоличествоКолес(), Замещает
КонецКласса
И в обычном модуле 1С (привязка реализации методов):
Функция МашинкаЛегковая_ДайКоличествоКолес(Знач ЭтотКласс) Экспорт
Возврат 4;
КонецФункции
Функция МашинкаБТР87_ДайКоличествоКолес(Знач ЭтотКласс) Экспорт
Возврат ЭтотКласс.м_колКолес;
КонецФункции
Далее возможно эти сущности создавать и оперировать ими как обычными объектными значениями 1С.
Т.е. обычные и привычные в других языках программирования классы. Синтаксис выбран соответствующий духу Бейсика и более всего похож на vb.net от Microsoft. Реализация также каноническая и претендующая на соответствие возможностям vb.net, c# или java.
Но это пока черновик (или версия-0) только ограниченно демонстрирующая эту технологию. Пример в демонстрационной конфигурации в конце этой статьи выбран не удачно. А некоторые недоработки и неприспособленность редактора текста модуля 1С к этой функциональности превращают код в чудовищную кашу. Поэтому из самой статьи этот код я убрал. По свидетельству немногочисленных выживших после увиденного «ЭТО вызывает быстротечный ООП головного мозга с неминуемым взрывом последнего». Ситуация изучается.
На словах. Код в конфигурации является некоторой переработкой шуточной программы <Hello World Enterprise Edition> на java. Т.е. он демонстрирует не просто ООП, а наихудшее его enterprise проявление. Поэтому даже название модуля сокращено до двусмысленности – ОопХелл. Собственно если это и демонстрационная программ, то точно не для первой статьи. На этом примере автор отлаживал и хотел продемонстрировать возможности компоненты в использования ООП-техник известных как <паттерны проектирования>. Также можно почитать у «заклятых друзей» — <Паттерны проектирования в ABAP примерах>. В общем – выглядит это пока чудовищно, но работает.
Тем кто просто пока интересуется «Что за зверь такой ООП?» я бы не рекомендовал скачивать и разбираться в версии-0. Даже из любопытства не всем нужно смотреть как делается колбаса. Можно ведь и заработать стойкое отвращение к этому вполне полезному и обыденному продукту. Более правильным будет почитать литературу и поиграться с vb.net или java. Если эта технология получит развитие, то здесь будет тоже самое или очень близкое.
Также должен предупредить ищущих быстрой практической пользы. Возможности компоненты пока ограничены и объекты компоненты с объектами платформы не взаимодействуют. Пока можно только поиграться в ООП. И то с риском для здоровья, как выяснилось. Просто следите за развитием технологии. В конце концов, делаю я это не только исключительно из тяги к прекрасному. В конце пути обязательно должен быть профит, просто пока, издалека, его не совсем отчетливо видно.
Отдельно ожидающим простоты и легкости кода типовых конфигураций. Разработчики проделали гигантскую работу убрав все сложности под капот платформы. И убрали они туда в том числе и ООП. ООП это инструмент для решения больших и сложных проблем. Простым он не будет никогда. Не бывает простых решений сложных проблем. В пределах возможностей читабельность кода повышать можно, но концептуальная легкость и простота с ООП не совместима.
Немного относительно самого ООП, хотя это не дискуссионная статья об ООП. Статью об ООП я только планирую. Проблематика ООП применительно к 1С корнями будет восходить к вопросам «Что есть решения от 1С или аналогичные продукты: это системы учета или управленческие инструменты?» и приземленней к 1С «Это программа (пул программ) или средаплатформа их разработки». Эти вопросы сами по себе масштабны и дискуссионны. Они не имеют единого ответа. Отвечая на них, человек скорее выбирает его и только его мировоззренческую позицию и эта позиция во многом определит его отношение к ООП. А сам по себе ООП это просто инструмент. Со своими преимуществами и недостатками. Инструмент для профессионалов.
Итак. Всех кто еще не испугался, не заснул и не переключился на что-нибудь полезное прошу за мной дальше.
ОопХелл.Подключить();
ОопХелл.Здрасьте();
Кусочек ужаса из демки:
Функция _Класс_ФабрикаАгентов_()
Возврат ""
"Класс ФабрикаАгентов"
"ВНУТР:"
" Конструктор() := ФабрикаАгентов_Конструктор"
"ВНУТР:"
" Перем м_фабрика, СТАТИК"
" Перем м_стдАгент"
"ЭКСПОРТ:"
" Свойство Фабрика, СТАТИК ЧТЕНИЕ := ФабрикаАгентов_Объект"
"ЭКСПОРТ:"
" Свойство СтандартныйАгент ЧТЕНИЕ := ФабрикаАгентов_СтандартныйАгент"
" Функция СделайАгента(имя_ Как Строка) ПЕРЕГРУЗКА := ФабрикаАгентов_СделайАгентаС"
" Функция СделайАгента(имя_ Как Строка, язык_ Как Строка) ПЕРЕГРУЗКА := ФабрикаАгентов_СделайАгентаСС"
"КонецКласса"
КонецФункции
...
Функция Агент_Поздоровайся(знач ЭтотКласс, другой_) Экспорт
Перем рез;
Перем другой_агент;
Перем другой_агент_неверб;
Попытка
другой_агент = другой_.ДайИнтерфейс("Агент");
Исключение
КонецПопытки;
Если другой_агент = Неопределено Тогда
Возврат СС.РезультатыМенеджер.Результат_Не_неАгент;
КонецЕсли;
Если другой_агент = ЭтотКласс.ДайИнтерфейс("Агент") тогда
Возврат СС.РезультатыМенеджер.Результат_Ок_сСобой;
КонецЕсли;
рез = другой_агент.ПримиСообщение(ЭтотКласс.МоеЗдрасьте);
Если не рез.Успех тогда
если рез = СС.РезультатыМенеджер.Результат_не_неПонял и ЭтотКласс.м_язык_другой <> Неопределено Тогда
рез = другой_агент.ПримиСообщение(СС.ФабрикаЗдрасьте.СделайЗдрасьте(ЭтотКласс.м_язык_другой));
Если рез = СС.РезультатыМенеджер.Результат_ок Тогда
рез = СС.РезультатыМенеджер.Результат_ок_сПереводом;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если не рез.Успех тогда
другой_агент_неверб = другой_агент.ДайИнтерфейс("НевербальнаяКоммуникация");
если другой_агент_неверб <> Неопределено тогда
рез = другой_агент_неверб.ПримиСообщение(СС.ФабрикаЗдрасьте.СделайЗдрасьтеЖест());
Если рез = СС.РезультатыМенеджер.Результат_ок Тогда
рез = СС.РезультатыМенеджер.Результат_Ок_Невербально;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат рез;
КонецФункции
По сути. Это пререлиз, черновик или версия 0. Т.е. сыровато, но сама технология, на мой взгляд, уже заслуживает публикации. Целью этой статьи является окончательно определиться с синтаксисом, поговорить, очертить границы и наметить план доработок. Особенно меня волнует синтаксис – его переделки наиболее болезненны. Также, несомненно, будут ошибки, и я буду очень благодарен, если мне на них укажут.
Техническое
Сразу. Версия-0: Количество аргументов методов ограничено 16. Значения по умолчанию для аргументов методов не поддерживаются. Объекты компоненты не поддерживают сериализацию. Коллекции 1С не поддерживаются. Обработка ошибок в зачаточном состоянии и малоинформативна, ассерты выведены в релиз. Течи памяти не проверял. Это черновик.
Компонента откомпилирована VS2024 для win32 (v140_xp, статическая линковка). Работаю я на win7-32 и тестирую (на данный момент) в 1С:Предприятие 8.3.6.2363. Все остальное в этой версии не пробовал. Ранее, в процессе экспериментов, были VS2010, Win2kSrv32 и платформы начиная с 8.3.4.365. Буду признателен, если кто подскажет типовые конфигурации которые стоит тестировать, а то все и везде это слишком много.
Все реализовано поверх родных интерфейсов 1С без какого-либо вмешательства в исходный код платформы. Связность с системой минимальна. Пул памяти 1С не используется. В системе объектов платформы не регистрируюсь, создать объекты компоненты можно только методами компоненты (Новый … — нельзя). Версия-0: своих ТИПов в систему также не добавляю, а мимикрирую под ФиксированнаяСтруктура. Моим типам платформа пока в отладочном табло свойства не разворачивает и это неудобно.
Стоимость экземпляра простейшего класса sizeof(long) + 3*sizeof(uintptr_t). Стоимость определителя класса не считал, но тяжелый. Стоимость каждого унаследованного или имплементированного интерфейса 3*sizeof(uintptr_t). Возможно доработать до 2*sizeof(uintptr_t) для простых классов. Стоимость вызова 1-2 virtual call. Переаллокация аргументов производится на стеке. Оценка быстродействия есть в демонстрационной конфигурации и здесь обсуждать ее считаю нецелесообразным. Затраты есть. Есть чуть резервов. На данном этапе и для данного типа приложения неважно.
Все объекты компоненты (и 1С) являются СОМ-объектам и время их жизни определяется их счетчиком ссылок. Соответственно все (за исключением синглетонов) подвержены <проблеме циклических ссылок>. Компонента никоим образом не контролирует это. Экземпляр класса уничтожается тогда, когда освобождены все ссылки на все его объекты-интерфейсы. Или зависает в памяти до завершения приложения, если прямо или опосредовано в его переменной сохранили его же самого. Определители классов – не синглетоны (версия 0). Объекты созданные компонентой нельзя сохранять в переменных модуля приложения без очистки этих переменных ПриЗавершенииРаботыСистемы(), или еще как. 1С выгружает компоненту до очистки переменных и попытка очистки переменных содержащих объекты созданные компонентой приводит к краху. По возможности нигде и никогда не используйте глобальные переменные.
Классы задаются текстовыми строками. Можно провести аналогию с реализацией SQL в 1С, которая тоже не является частью языка и в текстовом виде передается некоему механизму. Только SQL манипулирует данными, а escls манипулирует кодом. Механизм reflection в версии-0 не предусмотрен.
Несколько общих моментов
Делая это, я держал в голове некоторую концепцию «лингвистически корректного и академически правильного национального Бейсика». Поэтому «КлассДитя» НАСЛЕДУЕТ «КлассПапа». Наследует, а не расширяет, дополняет, углубляет, уточняет или еще как. Также можно писать «Свойство … ЗАМЕЩАЕМОЕ», а «Метод … ЗАМЕЩАЕМЫЙ» (версия-0: можно и наоборот – я все-таки не школьное сочинение проверяю).
Также считаю правильным, что класс определяется, а не описывается, декларируется или еще как. Название виртуальных методов замещаемыми тоже считаю правильным, поскольку без отсылок к истории и техническим деталям объяснить неподготовленному человеку в чем виртуальность не представляется возможным.
В моем понимании Бейсик – язык в первую очередь дружелюбный, а многословность его это обратная сторона дружелюбности и, иногда, необходимое зло. Сравните: «Асс Фуу(Баз Бар)»; и «Функция Фуу(Бар Типа Баз) Возвращает Асс». Обе конструкции концептуально, с учетом особенностей человеческого мышления, верны. Только они подходят к решению задачи с разных сторон.
Дружелюбность языка не означает его неполноценность. За критерий полноценности языка выбрана возможность выражения с его использованием общепринятой в программной индустрии концепции <паттернов программирования>.
Учет принципа разделения разработки. В иерархии наследования у каждого класса по умолчанию разные разработчики. Задача языка помочь каждому разработчику «дать» то что он хочет дать, и «не давать» ничего явно не указанного. В частности поэтому при трехуровневом наследовании конструкция «ЭтотКласс.БазовыйКласс.БазовыйКласс…» работать не будет. Разработчик «среднего» класса должен явно дать доступ своему наследнику к некоторой функциональности своего базового класса.
ООП – это зло, но ООМ (объектно-ориентированное мышление) — это добро. Добро невозможно без зла и единственный путь здесь – это сделать зло дружелюбным.
Документация
Объект класс – это совокупность объектов-интерфейсов класса. Объект-интерфейс класса создается компонентой и распознаются платформой как допустимое объектное значение. Его можно сохранять в переменные, передавать параметром, и т.д. В случае, если класс имеет секцию внутренних данных иили методов, то компонентой создается два объекта-интерфейса класса. Один публичный – его возвращает метод .СоздатьКласс(), а другой приватный – его получают в качестве первого параметра методы реализации. Имя класса это также и имя публичного объекта-интерфейса класса. Если класс наследует другой класс, то у него будет уже четыре объекта-интерфейса – публичныйвнутренний базового плюс публичныйвнутренний самого класса. Если у базового класса есть защищенные элементы (не доступные публично, но доступные наследнику), то у него создается еще один внутренний объект-интерфейс возвращаемый свойством .МойБазовый внутреннего объекта-интерфейса класса наследника. Если класс реализует (имплементирует) интерфейс, то у него будет создан еще один именованный объект-интерфейс. И так далее. Все объекты-интерфейсы класса дают доступ строго только к определенным для них элементам класса. Объект-интерфейс базового класса (.МойБазовый ) содержит варианты элементов до переопределения их наследником. Все объекты-интерфейсы класса имеют функцию .ДайИнтерфейс(ИмяИнтерфейса), которая возвращает соответствующий объект-интерфейс или неопределенно. Любой внутренний интерфейс получить способом .ДайИнтерфейс(…) нельзя. Все свойства и методы объектов-интерфейсов реализуют свою функциональность путем вызова методов объектов платформы заданных при определении класса.
Собственно ИНТЕРФЕЙС это специальная форма класса у которого не может быть переменных, все свойства и методы (процедуры и функции) замещаемые и без указания реализации — АБСТРАКТНЫЕ. Т.е. голая декларация метаданных некоторого контекста смысл обретающая тогда, когда класс этот ИНТЕРФЕЙС реализует.
В дальнейшем, для обозначения объекта-интерфейса класса я буду использовать принятый в 1С термин «контекст» для исключения путаницы с принятом в программировании термином ИНТЕРФЕЙС.
Сам объект компоненты содержит методы:
Функция ОпределитьКласс(ТекстОпределения, ОбъектРеализации) — создает, внутренне регистрирует и возвращает объект ОпределительКласса. В ТекстеОпределения может быть более одного определения класса иили интерфейса. Возвращается внутренний интерфейс объекта ОпределительКласса последнего определения.
Функция СоздатьДелегат(Объект, ИмяМетода) – создает объект Делегат. Этот объект имеет только один не именованный (версия-0) метод, при вызове которого, он вызывает заданный при его создании метод заданного объекта. Делегирует вызов. Тип метода (процедура или функция), а также аргументы определяются автоматически. Не именованный означает что вызвать его можно с любым именем — <делегат>.Вызвать(…) /.Выпонить(…) /.Провести(…) /.ДелайЧтоДолженБудьЧтоБудет(…) и т.д. Делегатов к свойствам и делегатов с привязкой аргументов в версии-0 нет.
Свойство СоздатьКласс – возвращает объект с динамически, по мере определения классов с публичными конструкторами, расширяемым набором методов с именами определяемых классов. Сигнатуры методов соответствуют сигнатурам определенных для класса конструкторов. Для использования в семантике <имя-переменной-компоненты>.СоздатьКласс.<имя-класса>(<аргументы-конструктора>).
Также, по мере определения классов, к объекту компоненты динамически добавляется свойства с именами классов возвращающие публичные интерфейсы объектов-определителей классов (объектов-определителей интерфейсов).
Свойство ПустаяСсылка – возвращает предопределенный в компоненте объект ПустаяСсылка (см. Деструктор)
Функция ДайТики() — версия-0, в тестовых целях возвращает GetTickCount()
Класс определяется методом компоненты .ОпределитьКласс(ТекстОпределения, ОбъектРеализации). Определение класса задается в текстовом виде через параметр ТекстОпределения. Через параметр ОбъектРеализации передается любой допустимый в 1С объект имеющий методы указанные в ТекстеОпределения класса в качестве привязки к реализации элементов класса. Первым параметром метода реализации должен быть параметр по-значению, в который компонента передает внутренний контекст реализуемого объекта.
Элементы класса – переменная, свойство, функция, процедура. Свойства и переменные не отличаются по способу обращения к ним через интерфейс класса – синтаксис свойства 1С. Но сами значения в случае переменных хранятся в самом экземпляре класса (или экземпляре определителя класса), а в случае свойств происходит обращение к методам платформы указанным в привязках реализации. Типы данных переменных – любые допустимые в 1С (а по сути любые COM-объекты). При создании все переменные принудительно получают значение 1С::неопределенно, а при уничтожении объекта принудительно очищаются (.Release()).
Общие элементы описания синтаксиса
В квадратных скобках [] опциональные параметры. Языковые конструкции в угловых скобках <>. Варианты в виде (<вариант-1> | <вариант-2>). БОЛЬШИМИ буквами термины. Термин это последовательность символов распознаваемая парсером как единое целое. На данный момент термины двуязычны ruen. Термин КЛАСС означает строку Класс или Class. Регистр символов значения не имеет. Термины могут быть многовариантными – н.р. КАК предваряющий тип параметра или переменной представляется строками As, Как, Есть, Это, Типа. Еще раз – это черновик — возможно что-то лишнее, а чего-то не хватает
Точка с запятой в конце строки определения элемента опциональна. Переход на новую строку игнорируется.
Имена элементов (далее <имя>)
<имя> — это имя элемента в соответствии с соглашением о именовании 1С. Первый символ или буква или ‘_’ далее буквы и цифры в любой последовательности. Регистр символов игнорируется.
Многоязычность в версии-0 не поддерживается. Только грамматика в части терминов двуязычна (ruen). Многоязычность имен впоследствии предполагается реализовывать с помощью специальных атрибутов. Например: [&EN = ClassFoo] КЛАСС КлассФуу.
На даный момент запрещается определять свойства (и переменные) с именами совпадающими с именами методов и наоборот. см.<задумано-но-не-сделано>::<элементы-по-умолчанию>
Запрещается определять свойства и методы с именами совпадающими с именами предопределенных элементов – н.р. СоздатьКласс, МойБазовый, Конструктор и т.д.
PS: Далее по тексту может встречаться <идентификатор>. В исходном BNF это <имя>.<имя>…<имя>. В версии-0 не поддерживается и читайте просто <имя>.
Привязка к реализации (далее <привязка>)
Указание привязки к реализации для методов (функций и процедур) передается в строке определения в виде … := <имя>. Это <имя> ищется у ОбъектаПлатформы и проверяется на соответствие соглашению о формате.
Функции и процедуры указанные в привязках должны иметь вид:
ФУНКЦИЯ <имя>(ЗНАЧ <класс> [, <остальные-параметры-если-есть>])
или
ПРОЦЕДУРА <имя>(ЗНАЧ <класс> [, <остальные-параметры-если-есть>])
Для свойств указание на привязку к реализацию задается в виде:
ЧТЕНИЕ := <имя-функции-чтения> ЗАПИСЬ := <имя-процедуры-записи>.
Функция чтения свойства должна иметь вид ФУНУЦИЯ <имя> (ЗНАЧ <класс>) и возвращать значение свойства.
Процедура записи должна иметь вид ПРОЦЕДУРА <имя> (ЗНАЧ <класс>, НовоеЗначениеСвойства). В параметр НовоеЗначениеСвойства передается значение, которое присваивается свойству в программе.
Одно из указаний на реализацию может быть опущено. Если не указано ЗАПИСЬ, то свойство становится ТолькоДляЧтения. Если не указано ЧТЕНИЕ, то свойство становится ТолькоДляЗаписи. Опускание и ЧТЕНИЕ и ЗАПИСЬ не допускается.
При вызове нестатических свойств и методов компонента в аргумент <класс> помещает внутренний контекст объекта экземпляра класса – ЭтотКласс.
При вызове статических свойств и методов в аргумент <класс> компонента помещает внутренний контекст объекта определителя класса – МойОпределитель.
Для абстрактных свойств и методов (помеченных атрибутом АБСТРАКТН(АЯ|ОЕ)) указание привязки недопустимо. Для абстрактных свойств допустимо указывать атрибуты ТолькоЧтениеТолькоЗапись. Если атрибут опущен, то свойство считается доступным и для чтения и для записи. При задании привязки к реализации в классе наследнике допустимо указывать только привязку разрешенную атрибутом <только-чтение-запись> абстрактного свойства.
PS: В текущей реализации ЭтотКласс и МойОпределитель это, конечно, просто имена переменных и могут быть любыми. Но настоятельно рекомендую использовать именно эти термины. Хотя это и близко к невозможному (а скорее очень трудоемко), но нельзя исключать, что в будущем они станут терминами языка. PPS: сами термины обсуждаемы, но рекомендация унификации остается.
Общее описание атрибутов
Атрибут СТАТИК означает, что элемент с этим атрибутом един для всех экземпляров этого класса и не имеет доступа к данным экземпляра класса, а только к таким же статическим элементам класса. По сути, статический элемент — это элемент объекта определителя класса, но присутствует и в контекстах экземпляра класса. В методы реализации статических элементов указанные в привязке первым параметром передается внутренний интерфейс определителя класса, а не внутренний интерфейс экземпляра класса. Таким образом статические элементы имеют доступ к другим статическим элементам класса, но не к элементам экземпляра класса. Публичные статик элементы доступны через обращение к определителю класса через объект компоненты. Совпадающие по определению статические свойства и методы наследника скрывают свойства и методы базового в контексте наследника.
Версия-0: первичная инициализация статических переменных не реализована. После создания объекта-определителя класса, функция компоненты ОпределитьКласс(…) возвращает приватный интерфейс определителя давая возможность провести первичную инициализацию внутренних статических переменных, если это необходимо.
Атрибут ПЕРЕГРУЗКА применим к функциям и процедурам и означает создание более одного метода с одинаковым именем, но отличающихся количеством иили типом данных аргументов. При вызове метода класс, на основании количества и фактического типа данных переданных параметров, переадресует вызов соответствующему методу реализации. Поддерживаются типы данных платформы ЧИСЛО, СТРОКА, ДАТА, БУЛЕВО, НЕОПРЕДЕЛЕНО, NULL, ТИП, ОБЪЕКТ. Также может быть использован термин ЛЮБОЕ, означающий что данный аргумент метода может принимать значение любого типа. Если тип не указан, то считается ЛЮБОЕ. Согласованность всего букета перегрузок проверяется для недопущения неоднозначного поведения. Атрибут ПЕРЕГРУЗКА обязательно явно использовать во всех вариантах метода, даже если он один, но вы допускаете его перегрузку у наследников. Атрибут трактуется как атрибут имени.
При сокрытии или замещении букета перегрузок из базового класса в наследнике всегда скрывается весь букет. Приоритет имени. Для «проявления» перегрузок из базового класса в наследнике их нужно явно определять. Версия-0: конструкция ИСПОЛЬЗОВАТЬ <…> не поддерживается.
Ограничение методики: Интерфейсы 1С не поддерживают концепцию перегрузки методов. Перегрузка реализована компонентой с использованием особенностей работы со значениями по умолчанию. Поэтому использование значений по умолчанию для последних, непересекающихся с остальными вариантами, аргументов принципиально невозможна. Для пересекающейся части аргументов возможна, но только одинаково для всех вариантов. Пример: Фуу(а1_) ПЕРЕГРУЗКА; Фуу(а1_, а2_) ПЕРЕГРУЗКА. Для а2_ значения по умолчанию невозможны. Для а1_ возможны, но только одинаково у всех вариантов.
Ограничения версии-0: а) Количество аргументов – 16. б) Алгоритм проверки согласованности, если указано ЛЮБОЕ, исключает другие типы данных по данному параметру, а не дополняет существующие.
Атрибуты замещения ЗАМЕЩАЕМ[АЯ|ОЕ], ЗАМЕЩАЕТ, ЗАМЕЩАТьОБЯЗАТЕЛЬНО, НеЗАМЕЩАТЬ, АБСТРАКТН[АЯ|ОЕ] . Определяют замещаемый (виртуальный) метод или свойство. Реализация указанная в наследнике замещает реализацию указанную у базовых классов. Таким образом реализация свойства или метода у класса единственна и определяется наследноком. Для абстрактного методасвойства реализация не указывается. Вызов абстрактного метода приводит к ошибке исполнения. В остальных случаях реализация должна быть указана обязательно. При определении интерфейса указывать атрибут абстрактности обязательно. Просто атрибут ЗАМЕЩАЕМ[АЯ|ОЕ] определяет метод как замещаемый и проводит процедуру замещение неуспех которой не является ошибкой. ЗАМЕЩАЕТ требует чтобы метод обязательно заместил что-либо или ошибка. ЗАМЕЩАТьОБЯЗАТЕЛЬНО указывет, что при определении наследника класса он должен обязательно заместить этот метод своей реализацией. НеЗАМЕЩАТЬ, наоборот, запрещает замещать данный метод наследниками. Возможно сочетание атрибутов – Замещает НеЗамещать, Замещает ЗамещатьОбязательно.
При указании атрибута АБСТРАКТН[АЯ|ОЕ] указание привязки к реализации считается ошибкой.
Версия-0: При создании экземпляра класса наличие не реализованный абстрактных элементов не контролируется. При вызове свойства или метода без реализации выбрасывается ошибка.
Если метод или свойство не имеет атрибутов СТАТИК или атрибутов замещения, то он считается ОБЫЧНЫМ (или скрываемым) методом экземпляра класса. Метод указанный у наследника скрывает собой метод базового класса в контексте наследника, но не замещает его в контексте базового класса. Если имя метода определяет букет перегрузок, то скрыты будут все перегруженные методы.
(версия-0: напрашиваются атрибуты НеСкрыватьСкрыватьОбязательно)
Области видимости элемента (далее <область>)
Область видимости (ВНУТР | ЗАЩИЩ[(Е|Ё)Н] | ЭКСПОРТ) влияет на присутствие элементов в контекстах класса:
— Публичная (термин ЭКСПОРТ) – элемент виден всем всегда и во всех контекстах.
— Внутренняя (термин ВНУТР) – элемент виден только через внутренний контекст ЭтотКласс
— Защищенная (термин ЗАЩИЩ(Е|Ё)Н) – элемент виден этому классу и его наследникам, но не через публичный контекст. Т.е. унаследовано присутствуют в контексте ЭтотКласс наследника и непосредственно в контексте возвращаемом свойством МойБазовый.
Может задаваться как секцией так и атрибутом определения элемента (версия-0: склоняюсь атрибут убрать и оставить только секции, т.к. может приводить к путанице. Или сделать атрибуты опцией языка.).
Имя секции задается термином области видимости с двоеточием в конце. Область видимости заданная атрибутом элемента имеет приоритет перед заданной секцией. По умолчанию, с начала определения класса секция устанавливается в ЭКСПОРТ.
Область видимости – это для точки вызова. Не для компилятора. Компилятор «видит» все. Заместить внутренний замещаемый элемент базового класса из производного можно, а вызвать нельзя.
Синтаксис строк определения элементов
Общий вид строки определения элемента: <определение-…> [,] <атрибуты-определения> [:= <привязка>] [;]
<определение-начало-класса>
[<атрибуты-класса>] КЛАСС <имя-класса> [НАСЛЕДУЕТ <идентификатор>]
Наследование сделано не прототипно. Т.е. базовый класс как самостоятельный объект «там» нигде не существует. В терминах 1С при объявлении базового класса происходит начальная инициализация «метаданных» класса «метаданными» базового класса. На данный момент наследование сделано одиночным (т.е. можно унаследоваться только от одного класса) и только публичным (т.е. все публичные методы базового класса становятся доступны через публичный интерфейс производного класса, в версии-0 изменение области видимости элементов не поддерживается). В принципе, применяемая модель позволяет делать и закрытое, и множественное и даже множественное виртуальное наследование.
<атрибуты-класса>
ДляНАСЛЕДОВАНИЯ – запрещает создание экземпляра класса. От такого класса можно только наследоваться.
НеНАСЛЕДУЕМЫЙ – от такого класса запрещено наследование.
<определение-конец-класса>
КОНЕцКЛАССА
В теле определения класса должно быть определение хотя бы одного элемента класса. Пустые классы не допускаются.
<определение-начало-интерфейса>
[<атрибуты-интерфейса>] ИНТЕРФЕЙС <имя> [НАСЛЕДУЕТ <имя>]
Допустимо вне тела другого определения. Версия-0: Вложенные определения не поддерживаются. Трактуется как начало определения нового интерфейса и до определения КонецИнтерфейса могут быть только декларации свойств, функций и методов. Указание атрибута АБСТРАКТН[АЯ|ОЕ] для элементов интерфейса обязательно. Элементами интерфейса могут быть только свойства, функции и процедуры. Переменные в интерфейсе недопустимы.
<атрибуты-интерфейса> не предусмотрены.
<определение-конец-интерфейса>
КОНЕцИНТЕРФЕЙСА
Обозначает конец определения объекта интерфейс или конец секции реализации интерфейса внутри класса. В случае конца определения интерфейса контролируется определения хотя бы одного элемента – пустые интерфейсы не допускаются (версия-0: надо разрешить). В случае конца секции реализации интерфейса полнота реализации не контролируется – допустимо реализовать интерфейс частично и окончательно реализовать его в наследнике.
<определение-реализации-интерфейса>
РЕАЛИЗУЕТ [ИНТЕРФЕЙС] <имя>
Означает начало секции реализации интерфейса классом. Продолжается до определения КонецИнтерфейса. Внутри этой секции описываются привязки абстрактных элементов интерфейса к конкретным методам реализующим их функциональность. Например, если в интерфейсе было определение Функция Фуу() Абстрактная, то в секции реализации должно быть определение Функция Фуу() <атрибут-замещения> := <привязка-реализации>. Реализация интерфейса должна находиться в публичной секции. Реализация интерфейсов внутренне или защищенно не предусмотрено (версия-0). Элементы интерфейса не доступны через контекст самого класса. Для доступа к ним необходимо вызвать метод .ДайИнтерфейс(<имя>), который возвращает контекст со свойствами и методами описанными в определении интерфейса. Или неопределенно, если класс не реализует запрошенный интерфейс. Если реализуемый интерфейс в свою очередь унаследован от других интерфейсов, то его реализация его свойств и методов автоматически приводит к неявной реализации соответствующих свойств и методов его базовых интерфейсов. Допустимо создавать несколько секций реализации интерфейса.
Версия-0: если у класса уже есть реализация одного из базовых интерфейсов реализуемого интерфейса (непосредственно или унаследовано), то генерируется ошибка; также, попытка реализации базового интерфейса, а не наследника приводит к ошибке.
<определение-переменная>
ПЕРЕМ <имя> [,] [<атрибуты-переменной>]
Объявление переменной. Допустимо только при определении класса и только вне блока реализации интерфейса.
<атрибуты-переменной> ::= [СТАТИК] [ТолькоЧТЕНИЕ | ТолькоЗАПИСЬ][<область-видимости>]
Если не указаны атрибуты <только-чтение-запись>, то переменная доступна и для чтелия и для записи.
<определение-свойство>
При определении интерфейса:
СВОЙСТВО <имя> [,] АБСТРАКТНОЕ [<только-чтение-запись>][<область>]
где
<только-чтение-запись>::= ТОЛЬКОЧТЕНИЕ | ТОЛЬКОЗАПИСЬ
При определении класса:
СВОЙСТВО <имя> [,] [<модификатор>] [<область>] [<привязка-свойства>]
СВОЙСТВО <имя> [,] АБСТРАКТНОЕ [<только-чтение-запись>][<область>]
где
<привязка-свойства>::= [ЧТЕНИЕ := <имя>] [ЗАПИСЬ := <имя>]
<определение-функция> и <определение-процедура>
ФУНКЦИЯ <имя> [,] [ПЕРЕГРУЗКА] [<модификатор>] [<область>] [<привязка>]
ПРОЦЕДУРА <имя> [,] [ПЕРЕГРУЗКА] [<модификатор>] [<область>] [<привязка>]
где
<модификатор> ::=
АБСТРАКТН(АЯ|ОЕ)
| СТАТИК
| (ЗАМЕЩАЕТ | ЗАМЕЩАЕМ(АЯ|ОЕ) | НЕЗАМЕЩАТЬ | ЗАМЕЩАТЬОБЯЗАТЕЛЬНО)
<привязка>::=
:= <имя>
<определение-конструктор>
КОНСТРУКТОР ([<список-аргументов>]) [ПЕРЕГРУЗКА] [<привязка>]
КОНСТРУКТОР ()
Привязка конструктора должна быть процедурой и указывать ее обязательно. Допустимо не указывать привязку для конструктора без аргументов и атрибута перегрузки при размещении его во ВНУТР/ЗАЩИЩЕН секции. В этом случае строка определения трактуется как переопределение области видимости конструктора по умолчанию. Таким способом определяется не создаваемый публично класс. Публично не создаваемые классы не добавляются к списку методов свойства компоненты .СоздатьКласс и не имеют статического метода .СоздатьКласс() в публичном контексте определителя класса. Метод .СоздатьКласс() присутствует только во внутреннем контексте определителя класса и, таким образом, доступен для статических свойств и методов класса. Унаследоваться от такого класса тоже нельзя.
Перед вызовом конструктора все переменные экземпляра класса устанавливаются в неопределенно. Вызывается конструктор самого младшего наследника. Синтаксиса делегирования вызова конструктора в версии-0 нет. Поэтому конструкторы базовых классов компонентой не вызываются! При необходимости вызова явно объявленного конструктора базового необходимо вызывать его вручную в процедуре конструктора класса в виде ЭтотКласс.МойБазовый.Конструктор([<параметры-конструирования-базового>]);. Вызван ли реально конструктор базового класса компонента не контролирует. На момент вызова конструктора класс уже полностью сконструирован и все замещаемые элементы замещены. В любом случае старайтесь избегать вызова виртуальных методов из конструктора и деструктора. При возникновении исключения в процедуре конструктора компонента перехватывает его, очищает переменные, удаляет выделенную память и пробрасывает исключение платформе. Что примечательно, платформа в этом случае его корректно перехватывает и краха не происходит. В отличие от деструктора – там платформа явно не готова к замысловатому сценарию после .Release(). Также, если вы успели сохранить ЭтотКласс в какой-либо переменной, после исключения в конструкторе крах неизбежен. Планирую перейти на передачу слабой ссылки на ЭтотКласс, как ужк сделано в деструкторе. В любом случае – старайтесь не допускать (не выпускать) исключений в конструкторе и деструкторе.
< определение деструктор>
ДЕСТРУКТОР () <привязка>
Привязка в определении деструктора обязательна.
Когда счетчик ссылок экземпляра класса достигает нуля компонента вызывает определенные для класса процедуры деструкторов начиная с наследников и к базовым. После этого компонента дополнительно принудительно очищает все переменные класса и освобождает память. В качестве значения ЭтотКласс процедуре деструктору передается специальный объект СсылкаНаКласс через который можно точно также получать доступ ко всем элементам класса. По выходу из тела процедуры деструктора ссылка, даже будучи сохраненной в какой-либо переменной, очищается и превращается в ПустуюСсылку. Попытка вызвать какие-либо элементы класса через пустую ссылку приводят к ошибке. ПустуюСсылку можно только сравнивать с объектом возвращаемым свойством компоненты .ПустаяСсылка. Класс удаляется вне зависимости от сохраненных где-либо ссылок на него.
Версия-0: Процедура деструктор не должна выбрасывать исключения!!! Приводит к краху на втором вызове деструктора!!!
<определение-секции-области-видимости>
ЭКСПОРТ:
ЗАЩИЩЕН:
ВНУТР:
Действие распространяется на все элементы класса до определения следующей секции или до конца класса. В начале класса по умолчанию устанавливается в ЭКСПОРТ.
<комментарии>
//<любой-текст-до-конца-строки>
Задумано, но не реализовано
— Наитивная поддержка коллекций 1С. Для языка обрабатывающего данные это очень важно.
— Первичная инициализация статических членов.
— Комментарии в строке.
— Переопределение области видимости элементов.
— привязка свойства на свойство
— Множественное наследование. Важно для реализации аццессоров коллекций.
— Языковая конструкция ИСПОЛЬЗОВАТЬ.
— Операторы. Есть основания полагать, что интерфейсы 1С позволяют реализовать концепцию операторов «сравнение» и операторов преобразования_к_ «БУЛЕВО», «СТРОКА», «ДАТА», «ЧИСЛО».
— Делегирование вызова конструктора базового класса.
— расширенные атрибуты.
— декларирование функций ос и сторонних dll.
— расширение алгоритма определение перегрузки методов до интерфейсов объектов.
— Свободные свойстваметоды, или свойстваметоды расширения. На данный момент все привязки обязаны соответствовать определенной сигнатуре. Возможно к контекстам класса подключать свойстваметоды без требования на первый аргумент. Возможно это новая языковая конструкции МОДУЛЬ.
— Типизация. Расширять применение вплоть до дженериков и до проверки типов данных методов привязки.
— Методы по умолчанию. Если метод с именем <имя> в контексте отсутствует, но есть свойство с именем <имя> и это объектное свойство с методом по умолчанию то вызываем этот метод. Естественными кандидатами на такие объектные свойства являются делегаты, объекты ТИП, и объекты имеющие метод с атрибутом МетодПоУмолчанию. До концепции typedef. Обратная ситуация – использование имени метода как свойства – естественная конструкция для возврата делегата метода. Не разрешать и разрешать только если явно указано определение соответствующего свойства.
— обвязка тестами
— демонстрационная реализация паттернов
— <вы можете дополнить (а лучше уменьшить) этот список>
Статус разработки.
Компонента реализует расширение языка, а язык должен быть бесплатным. Поэтому:
Использование представленной в статье компоненты в познавательных, образовательных и коммерческих целях бесплатно. Автор не исключает возможных коммерческих расширений технологии как самим автором, так и сторонними разработчиками при соблюдении условий бесплатности самого языка и ненанесении вреда коммерческим интересам компании 1С и ее деловой репутации. В случае использования в коммерческих приложениях автор готов заключить «договор с законным обладателем копии программы 1С по доработке ее в соответствии с ее функциональностью и без вмешательства в исходный код программы». В этом случае, при необходимости обеспечения юридических формальностей, автор оставляет за собой право устанавливать стоимость договора в пределах издержек автора на обеспечение юридической схемы.
В рамках своих возможностей, по мере накопления улучшений, исправлений и доработок я буду выкладывать их в публичном доступе.
В то же время, особенно на текущем этапе, поддержка и развитие технологии требует определенных затрат времени автора, которые он не может обеспечить без ущерба для себя. Поэтому автор просит, всех кто находит предложенную технологию интересной и полезной, о пожертвовании на ее разработку и совершенствование, в рамках индивидуального восприятия ее ценности.
Почта: v8classes@gmail.com
WMU: U110651501027
WMR: R444928807260
WMZ: Z529168937078
Спасибо.
Когда-то пытался реализовать подобие ООП на Windows Script Component (WSC), язык использовался JScript. Определения классов задавал похожим образом, только использовался синтаксис WSC (т. е. XML, по сути).
Бросил, когда понял, что если делать ООП, то это нужно делать с возможностью наследовать штатные объекты 1С. Да еще желательно так, чтобы получившиеся потомки могли быть использованы вместо штатных объектов (т. е. в качестве параметров стандартных функций и т. п.). Кроме того, при использовании COM, нужно забыть про кроссплатформенность, а также про веб-клиент, что весьма печально.
Однако, это лишь мой личный выбор, Бывают задачи, когда ООП реально не хватает. Согласен насчет мышления в стиле ООП. Каскадные вызовы общих модулей в типовых конфигурациях — ничто иное как суррогатная замена некоторых механизмов ООП.
Успехов, видно проделана большая работа.
Плюс поставил. Автор, конечно , гигант, но…
1)Хотел бы я иметь столько времени для всякой фигни 🙂
2)Все эти «игры разума» никак не помогут для внедрения 1с в жизнь реального предприятия. Впрочем, сильно и не помешают.
(1) Aphanas, Спасибо. Успех, удача и все что их сопровождает мне бы очень не помешали.
Относительно поддержки штатных объектов 1С — это пункт <задумано-но-не-сделано>::<поддержка-наитивных-…>. Технически это не составляет большого труда в отношении основных объектов (Массив, Структора, Запрос, т.д.). Все (практически все за редким исключением) объекты 1С поддерживают COM-аггрегирование. Это будущая конструкция Класс МойМассив НАСЛЕДУЕТ 1С.Массив. Здесь нужно понимать, что 1С.Массив это объект реализующий не один интерфейс. Как минимум на первых порах поддержки сериализации не будет (см.ниже). Другая возможная конструкция Класс МойМассив НАСЛЕДУЕТ ИНТЕРФЕЙС 1С.Массив. Реализацию такой конструкции можно начинать делать хоть сейчас и все встроенные методы 1С, которым нужен только интерфейс массива не отличат это от родного массива. Не сделал это в версии-0 только потому, что это увеличит связность с платформой. На данном этапе мне хотелось бы «расшириться» на разные версии платформы, разные ОС и т.д. Вычухать баги. Обрасти юнит-тестами и только потом «углубляться».
ПС: код 1С уже не отличает где класс компоненты имитируюший к примеру Структуру, а где Структура 1С. В демке это есть. Моя технология родная для 1С. Ну почти-почти родная..
Относительно кроссплатформенности я не до конца понял.
Если имеется ввиду .so для линукса и т.д., то плюсы работают везде где есть процессор. Можно хоть сейчас начинать готовить выпуск для STM32 и через n времени оно откомпилируется. Линукс это моя первоочередная задача. С Андроидом посложнее (и это вызов!), но тоже возможно. Но это будет версия-зависимый эксклюзив.
Если имеется ввиду поддержка клиент-серверных возможностей 1С, то это а) поддержка наитивных интерфейсов сериализации. б) регистрация некоторых объектов во внутреннем реестре 1С и, естесственно, загрузка компоненты на всех машинах. Все решаемо. Это я планирую для версии-1. Пока просто рано тратить время. Пока на боевой сервер мою компоненту не будут грузить не потому что она что-то не поддерживает. Надо достичь стабильности и доверия.
Спасибо.
(3)
Жесть, насколько тяжело читается текст последнего вашего сообщения.
http://foolks.org/samorazvitie/psixologiya-vliyaniya-negativnye-chasticy-ne-ne-ispolzovat-chasticu-ne/
Попробуйте меньше использовать «не» и текст сразу станет чище и понятнее.
А отдельно от платформы работает? Например из 1script?
(0) Зачем?
Код ООП красив в первую очередь наглядностью и уже потом своей парадигмой конструирования решения. Цена тоже известна — огромное количество переходов (вызовов функций и возвратов из них). Ваша реализация обещает только второе, но кому? Тем, кто не силен в процедурном программирование или у него ООП головного мозга? Аналогичное решение на 1С77 было изящней, но программисты 1С избегали и его всеми силами.
(6) ture,
OOP, or not OOP: that is the question!
… but baltik number nine my best suggestion!
Не нужен!
За работу ставлю плюс конечно, но… в реальных больших проектах это использовать? Вряд ли… Как задел на будущее? Ну не знаю. Без платформенной поддержки это, на мой взгляд, так останется любопытным концептом. Очередной «вариацией на тему», не более.
Далее идет вольное рассуждение, так сказать «на тему» и «пользуясь случаем»…
ООП 1С-ке не хватает-не хватает, это видно по тому же ЕРП 2, где средство (язык & инструментарий-конфигуратор) перестали справляться со сложностью продукта и по исходным кодам видно, как команда мучительно пытается что-то с этим сделать. Рецепта, кроме как повышения уровня абстракции, а в данном случае это ООП, нет. Но позвольте, ЕРП 2 только-только задышала, а тут что, опять переписывать? Да никто не пойдет на это, и я прекрасно понимаю почему. Потому что это адЪ. Но пытаются, пытаются конечно хоть что-то сделать. Вон и определяемые типы данных ввели. Видимо задел под ОО? Ну, пожмем-увидим, как говорится.
Я уже не говорю о поддержке многопоточности и асинхронности на уровне языка сразу, которые ой как нужны (да они есть, но с танцами и бубном). Но, как говорится, если вы такие умные, где ваши деньги? Не нравится 1С-ка — велкам, полно других языков, платформ и прочего. Дерзайте (это я уже себе говорю)!
Сейчас народ изгаляется кто как может и кто во что горазд. В кодах одной фирмы, которая занимается ЭДО (не скажу какой) формы обработки сделали «типа классы» и в таком микс-стиле написали все. Работает? А то. Но поддерживать и дорабатывать это? 8-(
В общем, согласно тезиса Великого Кормчего, «расцветают все цветы» и «соревнуются тысячи школ мысли» в бесконечной и неравной борьбе аристотелевой бинарной логики со сложностью квантового реального мира. Но, увы, «серебряной пули» пока нет как нет.
(7) 🙂 IS my best suggestion
Насколько я люблю, и насколько мне не хватает ООП в 1С, но ваша разработка меня не воодушевила.
Как уже говорили выше, ООП должно давать легкое понимание и читаемость кода, а здесь этим и не пахнет.
А вообще, мне, например, ООП в 1С нужно, чтобы не создавать какие-то свои классы «Здрасьте», а наследовать существующие объекты платформы, и тем более объекты конфигурации.
Вот как порой не хватает возможности взять и наследовать исходный документ или обработку… Например, есть КассовыйОрдер, а от него Наследуются ПКО и РКО. Сейчас приходится просто заниматься копированием. 1С сделала хоть небольшой шажочек в эту сторону — Расширения, но хочется полноценного наследования.
Плюс поставил, так как очень уважаю таких энтузиастов, которые хотят сделать продукт лучше, но, боюсь, настоящего решения можно ждать только от 1С.
За идею и реализацию однозначно плюс! Проект интересен. Планы серьезные (чистое множественное наследование это плохо и не нужно, но это имхо конечно ☺). За всем этим пока не вижу глобальной идеи — положим, появилась на свет стабильная версия (с дженериками, интернал/экстернал интерфейсами, лямбдами, тонной синтаксического сахара и другими прелестями) — какой профит это даст рядовому разработчику (возможность дополнить типовую коллекцию своим итератором и т.д. это хорошо, но хочется большего)? Хорошо, предположим, что образовалось коммьюнити, которое активно будет переносить базовые алгоритмы и структуры данных «от больших братьев» (от хешмэпов из Java, до leftpad из ноды ☺), но ведь вендор этого не поддерживает. Каким Вы видите проект в будущем (как он будет развиваться в прикладном смысле для рядовых 1сников)?
Автору респект. Но название 1С++ давно захвачено 🙁 с 2001 года продукт существует
Почитал. Ещё раз убедился, что в проблемно-ориентированном программировании (каким является 1с) — ООП нужен до уровня ширинки.
Автор, прошу простить меня за сказанное далее. Но получившийся у вас код выглядит ужасно не читабельно по отношению к привычному типовому коду 1С. Я бы от поддержки такого кода всеми силами бы старался отказаться. Ничего плохого про самое решение сказать не могу.
ОФФТОП: Всегда ненавидел эти Си++ заголовочные файлы где сначала обьявляют, что будет (нет не интерфейс, а именно тупо обьявление что будет реализовано), а потом в ЦПП файле реализация. Если хочешь добавить новый метод, приходится добавлять его дважды, неудобно и нечитабильно ИМХО. Когда пишу что-то свое с нуля то пишу этот класс в одном .h файле и не парюсь.
Я бы с удовольствием, но как мне понять — полезная ли это технология? Пока я читал статью, у меня взорвался мозг. И это при том, что я знаю, что означает «sizeof(uintptr_t)» и «virtual call».
Можете пояснить в двух словах, как мне (абстрактному «мне») это пригодится в жизни? ООП в 1С само по себе сомнительная штука, но даже если оно и нужно, то код из примеров вызывает у меня кровь из глаз.
Если совсем-совсем серьезно, то нам были бы полезны конкретные прикладные примеры, а не классические объяснения ООП на пальцах. В вузах, дай бог, все ООП учили и представляют себе. А вот представить себе, ради каких преимуществ нужно потратить время, изучив предлагаемую семантику классов (это ведь новый диалект, как ни крути, лишняя нагрузка на мозг) я как-то сходу не могу.
А так — очень круто, я помню еще первую вашу статью по внедрению в 1С:Платформу. Теперь бы эту энергию да в мирных целях куда-нибудь применить ))
Функция _Класс_Здрасьте_()
Возврат «»
«Класс Здрасьте»
«Защищен:»
» Конструктор()»
«экспорт:»
» Функция Идентично(другое_), Абстрактная»
» КонецКласса»
«»
«Класс ЗдрасьтеТекст Наследует Здрасьте»
«внутр:»
» Перем м_текст»
«экспорт:»
» Конструктор(текст_) := ЗдрасьтеТекст_Конструктор»
» Функция Идентично(другое_), Замещает := ЗдрасьтеТекст_Идентично»
» Свойство Текст ЧТЕНИЕ := ЗдрасьтеТекст_Текст»
«КонецКласса»
«»
«Класс ЗдрасьтеЖест Наследует Здрасьте»
«внутр:»
» Перем м_жест»
«экспорт:»
» Конструктор(жест_) := ЗдрасьтеЖест_Конструктор»
» Функция Идентично(другое_), Замещает := ЗдрасьтеЖест_Идентично»
» Свойство Жест ЧТЕНИЕ := ЗдрасьтеЖест_Жест»
«КонецКласса»
КонецФункции
Показать
просто жуть 🙁
Если так надо определять классы, то лучше не надо дальше что-либо делать.
Лучше взять идеи 1С++ и улучшить их, а не городить огород костылей и граблей(длинных и коротких).
(0) Я придумал, как тебе исправиться и очистить своё доброе имя на инфостаре.
Пишешь код на псевдо 1С (сам придумай разметку или возьми чистый шарп), код запихиваешь в текстовичек, а текстовичек отдаешь своей компоненте, которая вернет тебе экземпляр этого типа (объект класса). И вуаля!
Это будет медленней, чем писать на 1С раз в 100, т.к но это мерзкая гадость сделана намеренно самой 1С, чтоб не делали компоненты. Но! Какого рожна? Скорость в 1С? Не смешите меня. Это прокатит и будет круче поверь, чувак!
(6) ture, напишу свой взгляд на проблему
1С приближается к международному стандарту программирования, что уже радует.
И написать советы ЧТО надо бы сделать не приветствуются ни самими разработчиками 1С, ни сообществом обученных процедурному программированию.
Желания клиентов, не в расхождении с законом, всегда было в приоритете. Есть желание — должно быть простое решение. Точнее те, у кого «ООП головного мозга» видит решение в 3-5 строчек кода. Но в связи с процедурным программированием сделать ПРОСТО не получается. Рефакторинг хорошая штука, но в итоге код получается СОВСЕМ НЕ ЧИТАБЕЛЬНЫМ. Те, кто владеет ТОЛЬКО процедурным программированием ограничен и в решениях и в мышлении. И это навязывается при обучении как истинно верное решение. И потом все программеры с заложенным в них процедурным программированием думают, что все дураки (это моё мнение!!!).
Сколько сам писал предложений, всегда говорил, что вот вам идеи бесплатно, но, кроме минусов, ничего. Хотя спустя год-два к этому приходят. Вот написал предложения к расширениям. Минусов куча, но вот внедрили же условие КОГДА доп код запускаться ДО или ПОСЛЕ основного кода. Но изврат расширений так и остаётся. Да, будут «удобства», но если не в том направлении развивается, то зачем развивать именно неправильное направление?
(13) artbear, Спасибо за замечание. Само вырвалось. Вообще-то я это учитывал и в коде и в документации использовал везде 1С+классы. С картинкой вообще дурацкая история — редактор Инфостарт не хочет принимать статью без логотипа. Когда я скармливал ему первую статью, то уперся в это в последний момент и пришлось буквально на ходу фотошопить. А к второй статье подзабыл и пришлось старую вставлять. В названии статьи как-то само вырвалось. Отредактирую и текст пересмотрю. Картинку как доберусь до фотошопа переделаю на один плюс. Итак — проект называется 1С+классы. Картинка 1С+. Если, бог даст, будут у меня еще проекты то они будут идти под этой картинкой и именоваться 1С+<вербальное-имя-проекта>. Еще раз прошу прощения. Надеюсь на этом инцидент будет исчерпан.
Спасибо.
(19) ture, Вообще-то компоненту можно попросить скушать чистый шарп простой заменой грамматических таблиц парсера. По ООП-возможностям языки равноценны или будут почти равноценны. Я по крайней мере к этому стремился и стремлюсь. Сахорку подсыпать только надо да «запрещено то что не разрешено» аккуратно поразрешать.
Сами же языковые возможности у 1С конечно несравненно беднее шарпа (я о виртуальной машине 1С, т.е. о реализации методов). Но имеется потенциальная возможность и компилировать шарпом, или gcc или <ваш-выбор>. Лишь бы удобный Вам язык реализации виртуальные функции вызывать умел (ну то-есть с COM интерфейсами умел работать).
И, простите, а что не так с моим именем?
(23) Что нет так? Для специалистов «++» означает с++, а это весьма хмурые ребята, которых тошнит от CLR и с#, ибо это надругательство со стороны m$ над с++. А ты написал совсем что-то недостойное «++». Для программистов 1С, код не читаемый и похож на кашу, что типовые конфигурации и рядом не стояли. Т.е. получается как писали выше «ООП головного мозга».
Короче, прячь публикацию, пока тебя не запомнили потенциальные работодатели. Подредактируй ее на что-нибудь нейтральное и выводи снова (звезды вроде не должен потерять).
(21) Скоро, товарищ, скоро мы увидим как 1С сделает свободные тейблы и предложит самим написать классы, для работы с ними. Смекаешь? (так во всех ерп делают сегодня, а велосипед 1С некогда изобретать).
Классы в 8.4? На подлете точно, или рынок так и не увидит ЕРП от 1С, стоящую на ногах.
(24) ture,
По поводу ++ я уже ответил выше <artbear>. Это досадная ошибка. Нигде в самом коде и внутренней документации два плюса не используется. Название статьи и проекта будет отредактировано на «1С+классы».
По поводу каши почитайте ответ для <fishca>. В общем и целом в кашу код превращает импотентность 1С.
И знаете что… Спасибо! То что мои труд начинают сравнивать с типовыми конфигурациями уже лестно.
…и чего мы хмурые (смотрясь в зеркало), небритые вот только
ООП возник как более удобное средство разбиения системы на независимые части (удобно думать про неймспейсы) + идея хранить данные и методы их обрабатывающие рядом..
Ну не знаю.. может оно всё и работает — но пользоваться и поддерживать такой код — я не возьмусь.. страшно неудобно всё.
(0)
1. Для того чтобы сие творение хоть как-то отрывалось от земли, не говоря уже об взлете, я бы для начала пообщался на эту тему с зубрами 1С++
2. Пообщался на эту тему с зубрами опенконфа, снегопата && компани
3. И только после такого тесного сотрудничества и в теснейшем взаимодействии с ними разрабатывал хоть какой-то концепт технологии применительно к восьмерке.
Не надо отбрасывать опыт набития шишек, его необходимо использовать.
А так пока все эти слова про бейсик напоминают «запор мыслей, понос слов», вы уж извините за прямоту.
Есть серьезные сомнения по поводу применения данных наработок:
1. Крупные компании всегда будут против любых поделок не поддерживаемых официально 1С.
2. По собственному опыту знаю, что ++ далеко не всем нужен. Вообще-то очень редко нужен, только когда проектируется новые объекты. Спасибо фирме 1С, что они взяли на себя эту работу.
Если автору некуда девать свободное время рекомендую написать транслятор с языка 1С (без всяких ++). Коммерческий успех гарантирован. Вижу следующие применения:
1. Использование для пакетной обработки команд, что-то тип .bat на языке 1С
2. Просто что-то надо посчитать студентам типа экономистам.
3. А если он будет встроен в какой-нибудь бесплатный ексел, то ему цены не будет.
Однозначно плюс, т.к. любой прогресс начинается с энтузиазма одного человека, а далее подхватывается массой.
В любом случае ждем развития идеи. Будет развитие, возникнет и интерес со стороны 1С.
Описания классов подгружать из файла, реализации распихивать по модулям обработок — это структурированнее будет и от Класс_Метод позволит избавится.
ЭтотКласс как параметр — ну, в питоне живут с self и ничего. Хотя конечно, можно и исхитрится и обойтись без этого.
Недостаток «ЭтотКласс» — при вызове нельзя выбрать, вызывать ли строго метод из базового класса или возможно переопредлённый в наследнике. Но тоже решаемо.
Только это уже было, реализация на подобном принципе —http://infostart.ru/public/19332/
http://infostart.ru/public/541518/ — но это костыль ещё похлеще обсуждаемого.
Допилить то можно до боле-менее приемлемого состояния, но видимо, нет особой нужды в ООП в восьмёрке.
К тому же таки всё через COM — дополнительные задержки плюс линукс в пролёте. А нативные ВК — не поддерживают работу с объектами, только если с закатом солнца вручную, как в
Самое красивое, конечно же, было бы сделать реализацию на внутреннем движке 1С, по принципу снегопата, но релизо-зависимость… Хотя, в части работы с объектами 1С — она не такая сильная — с 8.2 ничего принципиально не менялось.
(30) serg61,OneScript же.
Какой кошмар…
За старания плюс, конечно, но такое ООП в 1С точно не нужно. Вот если бы кто взялся и реализовал модель, основанную на сигналах а-ля Smalltalk, это был бы реальный взрыв мозга. А тут только запутывание похуже злосчастной БСП.
(32) orefkov, Это вероятно какое-то или неточное прочтение или мое сумбурное описание.
Компонента полностью родная для 1С как и Снегопат. Я иногда использую термин 1С:COM, что подразумевает:
а) наследование от IUnknown
б) 1C:<типы данных> для параметров и возвращаемого значание
в) для возвращаемого значения не HRESULT, а любое допустимое в б)
г) ошибки в виде С++ исключения в 1С:<ошибка> формате (в т.ч. и через границу DLL)
Так построена и 1С и эта компонента, поэтому при компиляции под соответствующую платформу работать она будет везде, где работает и 1С. Сейчас выложена win32. Следущим шагом планирую lin32. Затем lin64. О win64 буду думать гхм… по политическим мотивам. Андроид и iOS не являются технически неразрешимой задачей, но там будет абсолютная версиозависимость. Поэтому это эксклюзив.
ЭтотКласс — калька с ЭтотОбъект, но не ЭтотОбъект во избежание конфликтов имен. Селф — по русски? Это не по-одинэсовски. Они где-то рассказывали, что у них целый отдел согласованиями имен занимается. Он такое не пропустил бы.
Вызвать метод базового класса — конструкция ЭтотКласс.МойБазовый.<имя-метода>
Свойство .МойБазовый возвращает именно контекст базового класса, без замещения виртуальных методов. Т.е. вызывается именно версия метода базового класса, а не наследника.
Возможность вызова ЭтотКласс.МойБазовый.МойБазовый.<имя-метода> подавляется принудительно. — разработчик базового явно должен дать такую возможность наследнику.
Подумываю только термин МойБазовый заменить на термин БазовыйКласс в окончательной версии. Т.е. чтобы было ЭтотКласс.БазовыйКласс.<имя-метода>
Если будет развитие проекта, то можно ввести специальную синтаксическую конструкцию для восстановления свойства БазовыйКласс в контексте базового у наследника для удобства разработчика.
Также (при развитии) в случае реализации множественного наследования видится ЭтотКласс.БазовыйКласс(‘имя-класса’).<имя-метода> к примеру, хотя наверное есть и другие варианты.
Подгрузить же текст определения класса разработчик и сам может откуда ему заблагорассудится. Даже (поскольку это рантайм) он может вывалить пользователю окошко с текстовым (или иным визуальным) редактором, чтобы тот сам себе класс сделал.
Конечно можно и компоненте метод-сахарок сделать типа .ОпределитьКлассИзФайла(…), но у меня плохие предчувствия, что только пойди здесь на поводу, и только и будешь писать код загрузки определения класса из всех всевозможный источников во всех мыслимых форматах с обработкой всех возможных и невероятных ошибок… Ну в общем это до конца жизни.
Без нормального IDE и IntelliSense (короче Снегопата) жизнь будет очень скучна при любом методе загрузки.
(30) serg61,
Сторонняя реализация языка 1С — это OneScript. Очень путевый проект. У меня есть большие надежды на сотрудничество с ними. Если мою разработку добавить к их проекту то получится полноценный «национальный Бейсик» с весьма развитыми выразительными возможностями. Если развить еще тему типизации до уровня Nemerle и атрибутов, то на java можно будет посматривать свысока. Их в теме просто еще не было и я не знаю их планов. С моей же стороны требуется сформулировать интерфейсы взаимодействия дабы не публиковать интерфейсы 1С. Тем более они мне немного тесноваты — и вперед.
Я подумываю не о трансляторе, а о компиляторе языка 1С в машинный код. Что-то уже намечается…
А в OpenCalc есть UNO-бейсик, а вся технология UNO сама по себе интересна…
А для крупных компаний таки да — <не нужен>. Или по крайней мере пока <не нужен>. Только если <это> вырастет в полноценный проект и только если они оголодают на тощем рынке. Вот тогда да — в очередь выстроятся. Пока это только «тюнинг» для любителей. Впрочем аналогия с авторынком и рынком авто-тюнинга абсолютно полная. Это одинаковая и описанная в литературе бизнес-модель.
Ну и конечно ООП нужен для ЕРП++, но не перескочить через Предприятие++, но для этого надо Бух++, БСП++ …
А в начале всего этого надо хоть пяток человек понимающих и 1С и ООП и необходимость такого пути.
(29) fishca, Спасибо. Я и пытаюсь с зубрами пообщаться. Только они, зубры, такие… к ним так просто не подойдешь. Без рабочего кода с одним «запором мыслей» вообще вариантов нет. Прошлая статья показала. Да и сейчас не гладко.
А за прорыв «запора мыслей» извините — накопилось. Материала много — я еще VB6 компилятору помогал, во free basic компиляторе копался, вот и с 1С не устоял. Судьба видно.
Нужно какое-то одно яркое практическое зерно. И народ потянется. Я вот только его никак ухватить не могу.
(16) eugeniezheludkov,
🙂 Вся компонента так написана. Пока. Но придет черед сурового gcc и придется рефакторить. Но это даже хорошо. Чем больше рефакторишь, тем меньше кода. А чем меньше кода, тем меньше глюков.
(38) так я как -раз в суровом gcc и компилю где у меня .hфайл сразу же содержит реализацию класса без объявления этого не наследуемого «недоинтерфеса»
ООП в 1С не нужен! И никогда не понадобится.
Сделайте возможность передать одну функцию в другую как аргумент. И замыкания.
Мысль, куда направить силы: есть отдельная каста извращенцев (в том числе больших и корпоративных), которые держат код не в конфигураторе. Даже ходить далеко не надо: взять ту же конвертацию или алгоритмы трансляции во всяких (трибуквы)-финансах. Пишут код в блокнотике, суют его в справочник, потом в конфе где-нибудь видим: Выполнить(Ссылка.ТекстАлгоритма)
И вот тут-то можно и развернуться с новшествами в языке: кодер бьёт код на вашем чудо языке, некоторый чудо-транслятор где-то в фоне «компилит» это в инструкции на чистом 1Се, который потом исполняется, собственно, платформой.
Честно, я был бы счастлив иметь возможность писать в конвертации хотя бы процедуры 🙂
PS. извращенцы были в хорошем смысле слова, хотя и плеваться иногда на них охота.
Автор молодец!!!
+ в карму! Только один вопрос, просвятите — зачем ООП в 1С? Что нельзя написать и какой профит на выходе?
Поставил +.
Но как такое юзать в продакшене?
И не может классическое ООП реализовать через интерпретаторы, кем 1с, собственно, и является.
(00) Выбор эксперта?
Новый макдиггер это!
(46)
главное чтоб python об этом не узнал, а то работать перестанет. Да и php вместе с js.
Про «интерпретатор 1С» промолчу.
(48) Ну в js жалкое подобие ООП.
А об «Про «интерпретатор 1С» промолчу.» — так Вы не молчите.
(49) он просто не забивал голову.
(0) помнишь, я говорил, что не интересно и избегают? еще есть ощущение, что я не хотел тебе помочь? Последуй совету.
(52) а если так?
(53) Все верно. Смысл был проиллюстрировать что начнет твориться, если взять так сказать Junior 1C программиста… И прилепить ООП полное в 9й версии 1С.
Если честно я не совсем чистый С++ изучаю, QTC++ — можно считать одним из диалектов С++.
Там много потенциально не безопасных моментов убрано.
Если чего-то не хватает то там самые распространенные библиотеки STL и BOOST.
То, что в QT убрали много не безопасных моментов — это меня да же радует.
Но без базовых знаний С++ например указатели, работа с памятью и т.п. мало что пойму.
Так что тихо едем и читаем Страуструпа и решаем упражнения 🙂
А сточки зрения работы — Системное администрирование.
Иногда приходится на низком уровне писать — утилиты, или например как вариант модули в SQL сервера — MS SQL и PostgreSQL поддерживают такое расширение. Хотя на практике не доводилось.
Если с точки зрения Системы учета от 1С (Платформа + конфа) — то же подойдет QT(ток поставить нужно не забыть) и все что мне от ООП не хватало, тех объектов, то просто зашить их в компоненту на Ntive API. ИМХО.
(54) нафиг Си++ ! Golang изучайте!
(55) А зачем Go?
(56) А зачем Си++ ??
(57) Хотя бы компоненты писать на Native API остальное за пределами данного ресурса.
Теперь ваш ответ.
(58) мой ответ целиком за пределами данного ресурса. если отвлечься от внешних компонент, на го пишется быстрее и очевиднее.
А я вот не освоил Го, задач как-то нет под него. Но любопытный язык, да
(59) Я себе то же немного жизнь упростил. Взял библиотеку QT да многие небезопасные моменты исключены. Да стандарт то же решил взять посвежее С++11 или С++14.
А чтоб писать быстрее и очевиднее — мне питон нравится. Поглядываю в версию 3.*
И таки да в базовой конфе Unix/Linux идет g++ (отнюдь не gcc-go) и питон.
И так с какими ЯП я чаще буду сталкиваться? Ответ увы очевиден.
Еще чтоб писать проще быстрее и очевиднее есть PHP7 в котором подкрутили
Быстродействие…
И да это мое ИМХО.
А так я не проти Go но увы… задач под него нет…
(61)
ээээээ… правда??? а я, дурень, руками его ставлю каждый раз. А «в базовой конфе Unix/Linux» вообще увело меня в размышления о вечном.
(61)
это bash, видимо.
(61)
слова «PHP» и «очевиднее» и в одном предложении у меня выдают ошибку компиляции, если честно.
Сойдёмся на том, что Qt — отличная штука 🙂 (кстати, есть порт для Go)
(61) базовый конфиг Unix/Linux это слакварь или, как минимум, гента. Там никакого g++ нет, не говоря про питон. А еще мне тут @nixel2007 показал вариант scratch. Так там даже echo нет. Вот это базовый так базовый.
(63) я чаще использую CentOS то же поправил немного сам дистриб 🙂 . Чисто для академического опыта собирал Gentoo ISO. и правил скрипт, для установки нужных пакетов автоматом. Почему чисто академический — так не используется у нас Gentoo. А когда нада один дистриб раскатать на много станций — тут уже ручками не поставить. Да и обновлять проще из локального дистриба. Дома клон убунты — Linux Mint. все что мне нужно робит. Т.к. дома я отдыхаю. Ну если есть у меня желание можно академические опыты с дистрибом поделать. И от одной убунты останется только ядро + php + mysql + apach+iptables — это к тому что из дистриба выпилить можно все что угодно и собрать как угодно.
(62) sh 🙂
если на PHP писать как положенно с анотациями и т.п. — т.е. соблюдать правила оформления кода, то вполне читаемо.
И вполне очевидно:) но да вы правы мало кто так делает :))))
Но примерно так же и фирма 1с требует оформлять код.
А про установку ручками — мне лень. чуть ниже отписался.
Ну да есть библиотечка скриптов(все что нужно чтоб получить требуемую мне базу), под те дистрибы которые использу.
Хостится в гите. Кочует со мной же. Выкачал, пересобрал. И раскатал. Притом пересборка просто пройдет рефлекторно наверное.
С комментариями согласен. Реализация ООП не стоит того, чтобы писать километры кода ради маленького функционала.
Неочевидно, трудно поддерживаемо другими разработчиками, визуально не читаемо.
Автор,
Чтобы код легко читался на интуитивном уровне, нужно как минимум изучить Питон, посмотреть Го.
Пытаться реализовать ООП в виде С++ на 1с нет смысла, потому что когда нет нативной поддержки от платформы будут ГРАБЛИ и КОСТЫЛИ.
Писать такой код тяжело и непотребно, он некрасив и неинтуитивен.
Почему так любят С++, потому что в свое время он был лаконичен, краток и красив (на английском языке).
Для русского языка код С++ не красив, потому что автор — англичанин с английскими образами и понятиями.
Чтобы код программы С++ был как минимум лаконичен и читаем непрограммистами, в вашем случае нужно :
1. Разделить интерфейс классов и реализацию на отдельные файлы.
2. Логически разделить отдельные классы на подклассы. Один класс реализует работу с пользователем, другой — внутренние механизмы работы с графической системой, вводом-выводом.
Третий класс — работу с другими классами.
3. Работа с пользователем должна быть реализована в классе в котором функции реализуют естественные команды на живом языке.
Например
функция повернуть_влево()
функция увеличить_ход()
функция сохраниться() — вызывает функции интерфейса внутреннего класса который реализует сохранение данных на диск и т.п.
функция дать_отчет() — формирует контекст получения данных, формирует пакет данных и выводит отчет.
Такой класс реализует инкапсуляцию внутренних методов во внутренних классах.
Пользователь системы, который видит ее в 1 раз видит:
1. Простые методы, простые классы, читаемые функции естественно понятные.
2. Если захочет, может залезть в реализацию и прочитать как оно сделано.
Эта концепция кстати, во всех серьезных книгах по С++ рассказывается авторами как азбука ООП.
Это не входит в парадигму ООП но является ДЖЕНТЕЛЬМЕНСКИМ навыком программирования.
(66)
(66)
Относительно синтаксиса реализации ООП. Язык 1С называется 1С-Бейсик. Поэтому я и пытался делать «по-бейсиковски», а не «по-питоновски».
Относительно читабельностиписабельности кода не-программистами. Эта теория 60-х годов прошлого века является утопией. Программист — это профессия и у него должны быть профессиональные знания, навыки и инструментарий. Не будет ООП понятен «и домохозяйке», как и принципиальная электрическая схема ее любимого гаджета. Увы.
Относительно поддержки «в платформе». Вы просто не поняли смысл этой статьи. Я еще в прошлой удивлялся, что поддержка в платформе есть, но разработчики 1С ее «не дают». Никто мне тогда внятно так и не ответил на вопрос «почему?». Вот я взял и просто практически доказал что полноценный ООП в 1С возможен даже без каких-либо изменений в коде платформы. Точнее было бы сформулировать «без желания руководства 1С будут грабли и костыли».
И кстати я нашел ответ на вопрос «почему?». На хабре оказывается есть статья от 1С в которой описана политика 1С в отношении языка. Он оказывается сознательно ограничен в функциональности. СОЗНАТЕЛЬНО!<Это своеобразное сочетание мощной платформы и разумно-ограниченного прикладного языка>
А относительно работоспособности компоненты… Сами посудите — больше года после пререлиза компоненты прошло, а она работоспособна. В очередных релизах платформы ее не «запретили». Она им не мешает. Она 1С-непротиворечива. Другой вопрос, что «сознательно ограниченные в языковых возможностях» 1С-ники ее толком не понимают и применить не знают куда. Это действительно беда.
А собственно об ООП я, извините, в дискуссию ввязываться не хочу. С моей стороны это будет не гуманно.
Посмотрите еще здесь:https://forum.infostart.ru/forum9/topic178313/
(67) Если обидел, извините. НЕ хотел порочить вашу работу.
Работа хороша, эпична, мощна.
Я просто вставил свои замечания. И вот почему.
1. Я за более 10 лет работы в 1с для себя лично выявил и придерживаюсь простых правил.
а. Нет такого кода, который нельзя было бы улучшить, причесать, надраить, вылизать, сбрызнуть одеколоном.
б. Любой код должен стремиться к красоте, интуитивности, приятности, читабельности.
Это общее стремление любых живых мыслящих организмов — к самоорганизации.
в. Когда программист перестает причесывать код, он покрывается пылью, гарью и спустя года перестает работать, потому что любая система — живая и ее нужно поддерживать (сдувать пыль, перетасовывать и т.п.)
г. Любой список из более чем 3 пунктов плохо читабелен (интуитивно, подсознательно).
Из этого простое правило — превращать любой плоский код, состоящий из большого количества процедур (независимых), в Дерево фунций и процедур (вложенных), который разбиты на файлы, модули и папки.
Каждая папка, модуль и функция в конце концов должны подчинятся правилу САМОДОКУМЕНТИРУЕМОСТИ.
Правило САМОДОКУМЕНТИРУЕМОСТИ:
1. как можно меньше комментариев (в идеале вообще без оных)
2. Названия функций точно и максимально лаконично (без потери смысла!) отражают свой функционал
Если вы внимательно задумаетесь над вышесказанным и ОСОЗНАЕТЕ оное, то поймете, что вашу документацию можно и нужно переделать к САМОДОКУМЕНТИРУЕМОСТИ
а ваш код разбить на Деревья.
Чем дело продолжилось? Вопрос не праздный, хотел с Вами связаться по практическому применению.