1с ооп или нет

Обновлено: 07.07.2024

Данная статья изначально была размещена на Infostart. Получила много положительных отзывов.
Я уже несколько лет плотно работаю с 1С и поэтому знаком с сильными и слабыми сторонами этой системы. Одной из таких слабых сторон я считаю отсутствие полноценного ООП (а не кириллица, как считают многие программисты не работающие с 1С :))
В этой заметке я постарался пропагандировать объектный подход к программированию в 1С. Надеюсь удалось.

Первое что меня поразило при знакомстве с 1С – это отсутствие ООП. Никаких описание классов, наследований, закрытых методов. А ведь любой код должен быть логически структурирован. А классы это то, что позволят это сделать с наименьшими нервами.
Потом, поработав с 1С, понял, что объекты конечно есть. Одни предопределенные (вроде «Документы», «Регистр сведений»), а другие зависят от фантазии программиста («Обработки»). Конечно, нет полиморфизма, нет наследования, но объектную модель построить можно.

Только другая проблема: большинство 1С-программистов все пишут в «процедурном стиле». Язык сам по себе толкает создать общий модуль. Потом поместить в этот модуль кучу процедур для обработки данных и поддерживать все это «спагетти» из вызова процедур.

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

Рассмотрим 1С в объектно-ориентированном подходе. Предопределенные объекты (Документ, Регистр. ) содержат код 3-х типов:

Все процедуры и функции в этих модулях, можно воспринимать как методы класса. Область видимости процедур или функция регламентируется ключевым словом «Экспорт» (здравствуй инкапсуляция). Правда, реквизиты нельзя сделать закрытыми, но это обходиться созданием глобальных переменных в самом модуле.

Только проблема в том, что большинство разработчиков в модуль формы «суют» код отвечающий за общую логику работы с данными. Сам грешен. По-моему, разработчикам платформы 1С не мешает в «модуль формы» добавить быстрый вызов «модуля объекта» (например через контекстное меню).

Теперь про объекты созданные самим программистом. На infostart встречал различные статьи о эмуляции объектно ориентированной модели. Но согласитесь, манипуляция со структурами для хранения данных – занятие муторное и не интуитивное. Я считаю, что лучшее решение, это воспринимать «обработки» как описание собственных классов.

Наглядный пример. В «Списке значений» мне не нравится диалог, вызываемый методом «ОтметитьЭлементы». Не хватает кнопок, которые выделяли (или снимали выделение) со всех пунктов. И вот обработка СписокЗначенийРас как раз и дает такой диалог. Добавляем обработку в конфигуратор, а потом вызываем:

СписокЗначенийРас = Обработки . СписокЗначенийРас . Создать ();
СписокЗначенийРас . Добавить ( "Пример1" );
СписокЗначенийРас . Добавить ( "Пример2" );
Если СписокЗначенийРас . ОтметитьЭлементы () тогда
СписокЗначенийРас . Данные . ОтметитьЭлементы (); // а это стандартный диалог
КонецЕсли;

К сожалению наследования в 1С нет. Поэтому методы и свойства которые есть у СпискаЗначений надо либо дублировать в обработке или обращаться к реквизиту который хранит оригинальный список значений (в моем случае это СписокЗначенийРас.Данные)

Теперь переходим в конфигуратор. Находим обработку СписокЗначенийРас и вызвав на нем контекстное меню, переходим в «модуль менеджера». Добавляем следующую функцию.

// Устанавливает или снимает (интерактивно) пометки у элементов списка значений.
// Заголовок - Заголовок окна диалога
// РабочиеДанные - список значений
Функция ОтметитьЭлементы ( Заголовок =Неопределено, РабочиеДанные ) Экспорт
Результат = Ложь;

ФормаОЭ = ПолучитьФорму ( "ФормаОтметитьЭлементы" );
ФормаОЭ . ПрочитатьДанные ( РабочиеДанные );
ФормаОЭ . ЧитатьДанныеПриОткрытие = Ложь;
Если Заголовок <> Неопределено тогда
ФормаОЭ . Заголовок = Заголовок ;
КонецЕсли;

РезультатФормы = ФормаОЭ . ОткрытьМодально ();
Результат = ( РезультатФормы = КодВозвратаДиалога . ОК );

Возврат Результат ;
КонецФункции

Теперь мы можем вызвать диалог еще проще.

сзДанные = Новый СписокЗначений ;
сзДанные . Добавить ( "Пример_1" );
сзДанные . Добавить ( "Пример_2" );
Обработки . СписокЗначенийРас . ОтметитьЭлементы ( "Заголовок" , сзДанные );

Чем не статический класс?
В подходе использования обработок как классов есть несколько недостатков.

  • Нет наследования. Хочется возможности указывать родителем хотя бы простейшие типы (СписокЗначений, ТаблицаЗначений, Дата, Строка…)
  • Класс-обработка показывается в общем списке обработок. Хотелось бы отдельный тип объектов.

На этом пока все. Надеюсь, заметка позволила вам разглядеть в 1С зачатки ООП 🙂

Первое что меня поразило при знакомстве с 1С – это отсутствие ООП. Никаких классов, наследований, закрытых методов. А ведь любой код должен быть логически структурирован. А классы - это то, что позволят это сделать с наименьшими нервами.
Потом, поработав с 1С, понял, что объекты конечно есть. Одни предопределенные (вроде «Документы», «Регистр сведений»), а другие зависят от фантазии программиста («Обработки»). Конечно, нет полиморфизма, нет наследования, но объектную модель построить можно.

Только есть другая проблема: большинство 1С-программистов все пишут в «процедурном стиле». Язык сам по себе толкает создать общий модуль. Потом поместить в этот модуль кучу процедур для обработки данных и поддерживать все это «спагетти» из вызова процедур.

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

Рассмотрим 1С в объектно-ориентированном подходе. Предопределенные объекты (Документ, Регистр. ) содержат код 3-х типов:

  • «Модуль объекта» - Код отвечает за конкретный экземпляр объекта, а вернее обработку данных этого объекта.
  • «Модуль формы» - Код отвечает за обработку действий пользователя.
  • «Модуль менеджера» - Код отвечает за операции над определенным типом объекта, без привязки к конкретному экземпляру. В обычных языках это зовется «статические методы»

Все процедуры и функции в этих модулях можно воспринимать как методы класса. Область видимости процедур или функций регламентируется ключевым словом «Экспорт» (здравствуй инкапсуляция). Правда, реквизиты нельзя сделать закрытыми, но это обходится созданием глобальных переменных в самом модуле.

А существование «модуля формы» - это вообще фишка 1С, которой можно гордиться. Этот модуль позволяет отделить код отвечающий за обработку действий пользователя и код который обрабатывает данные (Ни дать ни взять MVC).

Только проблема в том, что большинство разработчиков в модуль формы «суют» код, отвечающий за общую логику работы с данными. Сам грешен. По-моему, разработчикам платформы 1С не мешает в «модуль формы» добавить быстрый вызов «модуля объекта» (например через контекстное меню).

Теперь про объекты, созданные самим программистом. На infostart встречал различные статьи о эмуляции объектно-ориентированной модели. Но согласитесь, манипуляция со структурами для хранения данных – занятие муторное и неинтуитивное. Я считаю, что лучшее решение, это воспринимать «обработки» как описание собственных классов.

Наглядный пример. В «Списке значений» мне не нравится диалог, вызываемый методом «ОтметитьЭлементы». Не хватает кнопок, которые выделяли (или снимали выделение) со всех пунктов. И вот обработка СписокЗначенийРас как раз и дает такой диалог. Добавляем обработку в конфигуратор, а потом вызываем:

СписокЗначенийРас = Обработки . СписокЗначенийРас . Создать ();
СписокЗначенийРас . Добавить ( "Пример1" );
СписокЗначенийРас . Добавить ( "Пример2" );
Если СписокЗначенийРас . ОтметитьЭлементы () тогда
СписокЗначенийРас . Данные . ОтметитьЭлементы (); // а это стандартный диалог
КонецЕсли;

К сожалению, наследования в 1С нет. Поэтому методы и свойства которые есть у СпискаЗначений надо либо дублировать в обработке или обращаться к реквизиту который хранит оригинальный список значений (в моем случае это СписокЗначенийРас.Данные)

Теперь переходим в конфигуратор. Находим обработку СписокЗначенийРас и, вызвав на нем контекстное меню, переходим в «модуль менеджера». Добавляем следующую функцию.

// Устанавливает или снимает (интерактивно) пометки у элементов списка значений.
// Заголовок - Заголовок окна диалога
// РабочиеДанные - список значений
Функция ОтметитьЭлементы ( Заголовок =Неопределено, РабочиеДанные ) Экспорт
Результат = Ложь;

ФормаОЭ = ПолучитьФорму ( "ФормаОтметитьЭлементы" );
ФормаОЭ . ПрочитатьДанные ( РабочиеДанные );
ФормаОЭ . ЧитатьДанныеПриОткрытие = Ложь;
Если Заголовок <> Неопределено тогда
ФормаОЭ . Заголовок = Заголовок ;
КонецЕсли;

РезультатФормы = ФормаОЭ . ОткрытьМодально ();
Результат = ( РезультатФормы = КодВозвратаДиалога . ОК );

Возврат Результат ;
КонецФункции

Теперь мы можем вызвать диалог еще проще.

сзДанные = Новый СписокЗначений ;
сзДанные . Добавить ( "Пример_1" );
сзДанные . Добавить ( "Пример_2" );
Обработки . СписокЗначенийРас . ОтметитьЭлементы ( "Заголовок" , сзДанные );

Чем не статический класс?
В подходе использования обработок как классов есть несколько недостатков.

  • Нет наследования. Хочется возможности указывать родителем хотя бы простейшие типы (СписокЗначений, ТаблицаЗначений, Дата, Строка…)
  • Класс-обработка показывается в общем списке обработок. Хотелось бы отдельный тип объектов.

На этом пока все. Надеюсь, заметка позволила вам разглядеть в 1С зачатки ООП :)

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

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

Общий модуль "Класс_ФизическоеЛицо"

Здесь видно, что в качестве рабочей лошадки используется "Структура", хотя на ее место вполне подходит и "Соответствие". Первый недостаток заключается в том, что для вызова метода объекта необходимо использовать какое либо имя свойства для определения ссылки на модуль. Я для себя определил этим ключевым словом букву "ф". Но, методы и свойства чудесным образом объединились и теперь находятся в одной структуре (объекте) ссылку на который можно передавать и использовать почти в любом месте. Второй недостаток заключается в том, что контекст структуры не передается при вызове метода из этой структуры. Следовательно, необходимо первым параметром передать саму структуру. По этому все методы которые работают с данными объекта первым параметром получают саму структуру. Этот параметр я назвал «МойОбъект» (ну просто по тому что ключевое слово «ЭтотОбъект» занято). Третий недостаток заключается в том, что нет возможности сделать скрытыми свойства. Для себя я определил, что скрытыми будут те свойства, которые начинаются с символа «_» (подчеркивание) или их можно перенести в отдельное свойство (например, с именем «Скрытые»), состоящее из структуры только скрытых свойств. Что касается методов, то тут ситуация не такая однозначная. Ведь если процедуре или функции модуля не установить ключевое слово «Экспорт» то она будет недоступна из внешнего модуля, но она не будет доступна и для наследника. По этому если Вам необходимо использовать скрытый метод у наследников начинайте его так же как и скрытые свойства со знака «_» подчеркивания.

И так с инкапсуляцией мы разобрались. Теперь нам нужно решить вопрос с самым главным – наследованием. Смотрим следующий текст модуля:

Общий модуль "Класс_Сотрудник"

Обратите внимание - каждый класс располагается в отдельном общем модуле. Теперь давайте смотреть, что у нас получилось. Конструктор вызывает родительский конструктор и получает от него все свойства, которые были определены в родительском классе, а если он вызывает своего родителя мы получим и свойства прародителя.. Четвертым недостатком является то, что если вы полностью переопределяете конструктор дочернего класса, то вы должны самостоятельно позаботиться о создании всех свойств, которые создаются родительским конструктором. Пятым недостатком и на мой взгляд самым существенным является то, что ВСЕ методы которые использует потомок необходимо объявлять в модуле потомка (в примере это функция «Обращение»). Небольшой ложкой меда здесь служит то, что при последующем или повторном наследовании эти методы можно перенести потомку простым копированием. Этот же недостаток заставляет отслеживать самостоятельно создание новых методов и копирование кода наследования в дочерние классы.

Но в результате мы получили объектный полиморфизм.

Давайте посмотрим, как будут работать наши классы в прикладном решении:

Использование в прикладном решении:

Как видно из примера финальный код почти похож на стандартный ОПП (за исключением буквы «ф» перед методом и передачей самого объекта в качестве первого параметра) и такой подход можно смело назвать Подобием Объектно Ориентированного Программирования в 1С (ПООПс)

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

Можно, конечно, просто показать создание справочников, документов.

Но может как-то описать на аналогии с ООП? Есть такие материалы?

(1) Да я не спорю. Вопрос как объяснить.

"Вот это предопределенный класс справочников можете добавлять свои классы".

А у справочника может быть табличная часть это как с точки зрения ООП?

Что такое виртуальные таблицы и т.п.

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

В 1С я вот не могу просто взять и создать объект, чтобы у него функция была. Не хочу документ, хочу произвольный объект.

полиморфизм в 1с не нужен ибо нет строгой типизации
(6) С точки зрения архитектуры приватных членов класса вообще не существует.

(5) > Таки замечу, что одна из первичных парадигм ООП - возможность создать объект

Вопрос скорее как объяснить основы 1С по аналогии с ООП.

(8) > полиморфизм в 1с не нужен ибо нет строгой типизации

У реквизитов есть.

(13) С точки зрения ООП, полиморфизм — этто разная реализация одноимённого метода класса-потомка. Вызывающая сторона вызывает этот метод, рассчитывая на его наличие в связи с тем, что такой метод есть у класса-предка.

Например, класс-предок Документ обладает методом Провести() (или Записать в режиме проведения).
Каждый класс-потомок Документ.Реализация и Документ.БанкПриход реализует этот метод по-своему, двигает свои регистры.

"обучение программистов основам 1С" // Аналогии будут скорее вредны, чем полезны

Любая обработка - это класс.

2. Процедуры модуля менеджера - это методы класса, не надо создавать экземпляр класса для использования методов

А вы говорите, нету ООП.

Создай обработку - назови её "Фабрика документов", и пусть она тебе генерирует разные документы в зависимости от типа документа и передаваемых параметров, а также предопределенных настроек

Вот тебе и паттерн - фабрика или фабричный метод.

А вы говорите, нету ООП.

Мне вот не хватает "Интерфейсов":

можно было бы наследовать БСП-шные интерфейсы и оставалось бы писать реализацию

Я думаю, когда-то это появится.

Может есть какие-то материалы в которых это рассмотрено?
(21) Официальных нет. Фирма 1С всячески избегает этой темы. Они молчаливо согласились, что в 1С нет ООП, а встроенный язык программирования является неполноценным скриптовым языком типа JavaScript.

(17) соглашусь, тут не с ООП аналогии надо проводить, а, например, с EJB.

JBOSS - сервер приложений, сам разруливает где у него там база и где сеть, только клиента своего не имеет. Но переучивать сениор жавистов на 1С - такая себе инвестиция. А джуны и тем более не жависты сами EJB боятся и не понимают.

(0) > может как-то описать на аналогии с ООП?

Зачем?
Вам работники нужны или нытики, мечтающие о полноценном ООП в 1С?

ИМХО, задача, которую вы ставите, - идиотизм.

Вы хотите научить ребёнка плавать и для этого намереваетесь прочитать ему несколько лекций по гидростатике, гидродинамике и физиологии? Ну-ну. С точки зрения общего развития это безусловно будет полезно слушателю. Только надо быть готовым к тому, что плавать он от наличия этих знаний не начнёт.

1С - это предметно-ориентированная среда. Если базовых начальных знаний по программированию у ваших студентов совсем нет, то может быть им и нужно пару лекций на эту тему. Если же вы готовите 1С-ников из людей, уже имеющих программистские знания, то это будет абсолютно лишним и ненужным. Им нужны конкретные прикладные знания - методы и подходы работы с конкретными объектами (справочниками, документами, регистрами, отчетами и пр.).

Читайте также: