What is pure architecture in simple words?
Clean architecture is an approach to organizing code in which the business logic of your application does not depend on the implementation details. Imagine that you are building a house: the foundation and supporting structures (business logic) must be independent of what wallpaper you choose or what tile you put in the bathroom (interface, database).
Basic principles of clean architecture:
Division of responsibilities — each module is responsible for its own task. The module for working with documents should not be engaged in drawing forms.
Independence from the framework — business logic should not be tightly tied to the 1C platform.
Testability — the code can be checked without running the entire system.
Dependency direction — internal layers are not aware of the existence of external ones. Business rules do not depend on how data is stored in the database.
Features of the 1C platform
Before talking about pure architecture, you need to understand the specifics of 1C. This is not just a programming language, but a whole platform with its own rules of the game.
Built-in language and metadata are closely interrelated. You can't just take and write code separately from the configuration — everything lives inside the platform.
Object model imposes a certain structure. Documents, directories, registers are not just classes, but objects with built-in behavior.
Transactional model works according to its own laws. You cannot fully control the work with the database, as in ordinary applications.
Forms and interface are created through the configurator, not written in code from scratch.
Does it sound like pure architecture is impossible? Not really, you just need an adapted approach.
Is pure architecture possible in 1C?
The short answer is: in the classic form, no, but you can create something similar and very useful.
1C will not give you complete independence from the platform. You won't be able to take the business logic and transfer it to Python or Java. But you can organize the code so that it is understandable, supported and relatively independent of specific implementations.
Main goal — not to achieve the ideal clean architecture from the textbook, but to write code that is easy to understand and modify. This is much more important than theoretical purity.
Architecture layers in the context of 1C
Let's take a look at how you can highlight layers in a typical 1C configuration.
Presentation layer
These are forms, commands, reports — everything that the user interacts with. This layer has a minimum of logic, only work with the interface.
❌ Bad example:
// In the document form module
Процедура ПровестиНаСервере()
// We immediately write to the database, calculate, check
Запрос = Новый Запрос;
Запрос.Текст = "SELECT...";
// 50 lines of code with calculations
Объект.Записать();
КонецПроцедуры✅ Good example:
// In the form module
Процедура ПровестиНаСервере()
МодульДокументов.ПровестиДокумент(Объект);
КонецПроцедурыBusiness logic layer
This is where the rules of your business live. How to calculate a discount, when a document can be posted, what checks need to be performed.
In 1C, these are usually common modules with a server context. It is good practice to divide them by domains: working with prices, working with balances, calculating salaries.
// GeneralModule: WorkWithPrices
Функция РассчитатьИтоговуюЦену(Номенклатура, Количество, Контрагент) Экспорт
БазоваяЦена = ПолучитьБазовуюЦену(Номенклатура);
Скидка = РассчитатьСкидку(Контрагент, Количество);
Возврат БазоваяЦена * Количество * (1 - Скидка / 100);
КонецФункции
Функция РассчитатьСкидку(Контрагент, Количество)
// Here is only the logic of calculation
Если Количество > 100 Тогда
Возврат 15;
ИначеЕсли Контрагент.VIP Тогда
Возврат 10;
КонецЕсли;
Возврат 0;
КонецФункцииPlease note: The function does not know where the data comes from and where it is written. It just does the calculation.
Data access layer
This layer encapsulates the work with the database. All queries, reading and writing of objects should be here.
// GeneralModule: NomenclatureRepository
Функция ПолучитьБазовуюЦену(Номенклатура) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"SELECT
| NomenclaturePrices.Price
|FROM
| RegisterInformation.PricesNomenclature AS PricesNomenclature
|WHERE
| NomenclaturePrices.Nomenclature = &Nomenclature";
Запрос.УстановитьПараметр("Nomenclature", Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Цена;
КонецЕсли;
Возврат 0;
КонецФункцииNow, if the price storage structure changes, you will only need to correct this module.

Practical techniques for improving architecture
Common modules instead of code in objects
Do not write all the logic in the document and reference modules. Take it out to the general modules.
Instead of:
// Document module Sale of Goods
Процедура ОбработкаПроведения()
// 200 lines of logic
КонецПроцедурыDo:
// Document module
Процедура ОбработкаПроведения()
МодульРеализации.Провести(ЭтотОбъект);
КонецПроцедуры
// GeneralModule: ImplementationModule
Процедура Провести(Документ) Экспорт
// Conducting logic
КонецПроцедурыUse parameters instead of global context
Pass data explicitly through function parameters, and do not reach for global variables.
Bad:
Функция РассчитатьСумму()
// We take data from an unknown source
Возврат Объект.Цена * Объект.Количество;
КонецФункцииGood:
Функция РассчитатьСумму(Цена, Количество)
Возврат Цена * Количество;
КонецФункцииSeparate reading and writing
One module reads the data, another processes it, and the third writes it. This simplifies testing and understanding of the code.
Minimize logic in forms
Forms should only display data and respond to user actions. All processing should be performed in the server modules.
Create facades for complex operations
If the operation involves many steps, create a single entry point.
// GeneralModule: OrderFacadeDesign
Процедура ОформитьЗаказ(ДанныеЗаказа) Экспорт
ПроверитьДанные(ДанныеЗаказа);
Заказ = СоздатьДокументЗаказа(ДанныеЗаказа);
РезервироватьТовары(Заказ);
ОтправитьУведомление(Заказ);
Заказ.Записать();
КонецПроцедурыTypical mistakes and how to avoid them
First mistake: everything in one module. The developer creates a huge common module, where there are functions for all occasions. Separate the code by meaning: a module for working with prices, a module for working with balances.
Error two: the logic is smeared over the forms. The same check or calculation is copied into a dozen forms. Take the duplicate code to the common modules.
Mistake number three: requests everywhere. The code directly accesses the database from anywhere. Create repositories for working with data.
Mistake four: dependence on details. Business logic knows about the structure of forms or specific database fields. Isolate implementation details.
Mistake five: ignoring modular tests. If the code cannot be tested, then the architecture is bad. Write the code so that it can be checked separately from the entire system.
Example of refactoring real code
Let's imagine a typical situation: processing a sales document.
Before refactoring:
// Document module Sale of Goods
Процедура ОбработкаПроведения()
// Right here we check the balances
Запрос = Новый Запрос;
Запрос.Текст = "SELECT Remainders...";
// We calculate the amounts
ИтоговаяСумма = 0;
Для Каждого Строка Из ТабличнаяЧасть Цикл
Строка.Сумма = Строка.Цена * Строка.Количество;
ИтоговаяСумма = ИтоговаяСумма + Строка.Сумма;
КонецЦикла;
// Record the movements
Движения.ТоварыНаСкладах.Записать();
// Checking the counterparty
Если НЕ Контрагент.Активен Тогда
ВызватьИсключение("Counterparty blocked!");
КонецЕсли;
КонецПроцедурыAfter refactoring:
// Document module
Процедура ОбработкаПроведения()
МодульРеализации.Провести(ЭтотОбъект);
КонецПроцедуры
// GeneralModule: ImplementationModule
Процедура Провести(Документ) Экспорт
ВалидацияКонтрагентов.Проверить(Документ.Контрагент);
РасчётСумм.РассчитатьСуммыДокумента(Документ);
РепозиторийОстатков.ПроверитьНаличиеТоваров(Документ.Товары);
ДвиженияДокументов.СформироватьДвижения(Документ);
КонецПроцедурыNow each part of the logic lives in its own module, the code is easy to read and test.
Quality control tools
SonarQube for 1C helps to find problems in the code: duplication, complex functions, violations of standards.
EDT (Eclipse Development Tools) provides more advanced development capabilities compared to the standard configurator.
Vanessa Automation allows you to write automated tests to check system behavior.
Development standards from 1C and the community help to maintain a consistent code style in the team.
When to apply clean architecture
Not every project needs a perfect architecture. If you are doing simple processing for a one-time data upload, you should not build a complex module structure.
Clean architecture makes sense when: the project will live long and grow, a team of developers is working on the code, requirements often change, high reliability and testability are needed.
For small configurations and simple modifications, basic principles are sufficient: division into modules, no duplication, and clear names.
Conclusions
Clean architecture in 1C in its classic form is impossible due to the peculiarities of the platform. But applying the principles of clean architecture makes the code clearer, more reliable and easier to maintain.
Start small: take the logic out of the forms into general modules, divide the code by responsibility, write small functions with clear names. Don't strive for perfection right away — improve the architecture gradually, as the project grows.
Remember: the goal of architecture is not to create beautiful diagrams, but to make the code easy to understand and change. If your code solves this problem, you are on the right track.
You can learn the basics of architecture, design patterns and best practices in 1C development in Codice — our platform for learning programming. We analyze complex topics in simple language, with examples from real practice.
And we also have a cool Telegram channel with a friendly community of developers where you can ask questions, share experiences and find like-minded people.
Join us!
