1Cで他の誰かのコードを操作したことがある人は誰でも、少なくとも一度は同じ感覚を経験したことがあるはずです。モジュールを開くと、800行のプロシージャがあり、 「データを処理する」。 コメントなし。変数「a」、「b」、「時間」を使用。そして、あなたは理解します。半年後、あなた自身のコードが誰かにまったく同じ感情を引き起こす可能性があることを。
それでは、 コードが読みやすく、予測可能で、サポートしやすい状態を維持するために、1Cでプロシージャと関数を書く方法。
手順と機能の違い
一見すると、すべてが単純です。関数は値を返しますが、プロシージャは値を返しません。しかし、この単純さの背後に、重要な設計原則が隠されています。
機能 これは質問です。あなたはシステムに何かを尋ねて、答えを得ます。データベースの状態を変更したり、ユーザーにメッセージを表示したりする必要はありません。単に計算して結果を返します。
Функция РассчитатьСуммуСоСкидкой(Сумма, ПроцентСкидки)
Возврат Сумма - Сумма * ПроцентСкидки / 100;
КонецФункции手順 これはコマンドです。ドキュメントを書き込む、メールを送信する、表の部分を埋めるなど、システムに何かをするように依頼します。アクションを実行し、結果を返しません。
Процедура ЗаполнитьЦеныВТабличнойЧасти(ТабличнаяЧасть, ТипЦен)
Для Каждого Строка Из ТабличнаяЧасть Цикл
Строка.Цена = ПолучитьЦенуНоменклатуры(Строка.Номенклатура, ТипЦен);
Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;
КонецПроцедуры関数がデータを書き込み、結果を返すことに気づいた場合は、ロジックを 2 つの部分に分割する必要があることを示す信号です。
名前付け: コードはコンパイラではなく人間が読みます
プロシージャまたは関数の名前は、あなたの後にコードを読む人との契約です。良い名前はコメントを不要にします。
悪い名前 は、目的を示すものではありません。
// 何を処理しますか?どのようなデータですか?なぜですか?
Процедура ОбработатьДанные()
// 具体的に何を確認しますか?どのような書類ですか?
Функция Проверка(Док)
// 「実行」はタイトルの中で最も無駄な単語ですроцедура ВыполнитьОперацию()良い名前 動詞を含み、特定の動作を説明します。
Процедура РассчитатьСебестоимостьПоПартиям(ДокументОбъект)
Функция ПолучитьОстатокНоменклатурыНаСкладе(Номенклатура, Склад, Дата)
Функция ЕстьПравоНаСкидку(Контрагент, СуммаЗаказа)実際に機能するいくつかのルール:
質問機能は、「取得」、「計算」、「検索」、「あり」(ブール値の場合)の単語から始めます。
コマンドプロシージャは、「入力」、「書き込み」、「送信」、「削除」、「設定」という単語から始めます。
長い名前を恐れないでください。「契約者への期間の支払い額を受け取る」は、「金額を受け取る」よりもわかりやすいです。
パラメータ:少ない方が良い
プロシージャに5つ以上のパラメータがある場合は、何かがうまくいっていません。これは単なる美しさの問題ではありません。パラメータが多いということは、プロシージャが多すぎるか、データの構造が悪いことを意味します。
問題:
Процедура СоздатьЗаказ(Контрагент, Склад, Менеджер, ДатаОтгрузки,
ТипЦен, ВалютаДокумента, Организация, Комментарий, Приоритет)
// ...ドキュメント作成の40行
КонецПроцедуры解決策 — 構造:
Функция НовыеПараметрыЗаказа()
Параметры = Новый Структура;
Параметры.Вставить("Counterparty");
Параметры.Вставить("Warehouse");
Параметры.Вставить("Manager");
Параметры.Вставить("Date of shipment", ТекущаяДата());
Параметры.Вставить("PriceType");
Параметры.Вставить("Currency");
Параметры.Вставить("Organization");
Параметры.Вставить("Comment", "");
Параметры.Вставить("Priority", 0);
Возврат Параметры;
КонецФункции
Процедура СоздатьЗаказ(ПараметрыЗаказа)
// クリーン、明確、拡張可能
КонецПроцедурыパターン「パラメーターコンストラクタ関数」は、1Cで最も便利なテクニックの1つです。既存の呼び出しを中断することなく、新しいパラメータを追加できます。
単一責任の原則
これはおそらく、1Cコードで最も頻繁に破られる最も重要な原則です。1 つの手順で 1 つのことを行う必要があります。
アンチパターン — 「手順の組み合わせ」:
Процедура ОбработатьДокумент(ДокументОбъект)
// 入力チェック — 50 行
// 金額の計算— 30行
// 動きの形成— 100行
// 通知の送信 — 20 行
// 取引先ステータスの更新 — 25 行
// ログ — 15 行
КонецПроцедурыこの手順はテストできず、デバッグが難しく、何かが壊れたとき(そしてそれは壊れます)、240 行すべてを読み直すことになります。
正しいアプローチ:
Процедура ОбработатьДокумент(ДокументОбъект)
ОшибкиЗаполнения = ПроверитьЗаполнениеДокумента(ДокументОбъект);
Если ОшибкиЗаполнения.Количество() > 0 Тогда
ВывестиОшибкиЗаполнения(ОшибкиЗаполнения);
Возврат;
КонецЕсли;
РассчитатьСуммыДокумента(ДокументОбъект);
СформироватьДвижения(ДокументОбъект);
ОтправитьУведомление(ДокументОбъект);
ОбновитьСтатусКонтрагента(ДокументОбъект.Контрагент);
КонецПроцедурыこれで、各操作が分離されました。合計を計算するロジックを変更する必要がある場合は、どこを探すべきかが正確にわかります。通知の送信ができなくなった場合、計算コードを読み直す必要はありません。
エラー処理:問題を隠さない
最も一般的な間違いの1つは、例外を黙って飲み込むことです。
すべきではないこと:
Процедура ОтправитьДанныеВоВнешнююСистему(Данные)
Попытка
// ...送信中
Исключение
// 空っぽです。まあ、送信されなかっただけです。
КонецПопытки;
КонецПроцедуры3か月後、会計士が来て、「昨年の夏からデータが消えない」と言います。そしてログには何もありません。
正しい方法:
Процедура ОтправитьДанныеВоВнешнююСистему(Данные)
Попытка
// ...送信中
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("IntegrationExternalSystem",
УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение "Failed to send data: " + ТекстОшибки;
КонецПопытки;
КонецПроцедуры黄金のルール:処理方法がわかっているエラーのみをキャッチします。残りはログに記録して上に転送します。
エクスポート:すべてを公開しないでください
1C では、すべての関数に「エクスポート」を設定することができます。これにより、モジュールがダンプに変わり、何が公開APIで、何が内部キッチンであるかを理解することができなくなります。
ルールは簡単です。プロシージャまたは関数は、他のモジュールが実際に必要な場合にのみ「エクスポート」修飾子を受け取ります。それ以外は、自由に変更できるプライベート実装です。
// これはパブリックAPIモジュールです—よく文書化されており、安定した契約です
Функция РассчитатьСтоимостьДоставки(Параметры) Экспорт
// ...
КонецФункции
// これは実装の内部部分です—エクスポートなし
Функция ПолучитьТарифнуюЗону(АдресДоставки)
// ...
КонецФункции返される値:予測可能にする
関数は常に同じタイプの値を返す必要があります。関数が状況に応じて文字列、数値、または未定義を返す場合、各呼び出しコードは探偵に変わります。
悪い点:
Функция НайтиКонтрагента(ИНН)
Запрос = Новый Запрос("...");
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат Ложь; // 時々ブール値
КонецЕсли;
Возврат Результат.Выгрузить()[0].Контрагент; // 時々リンク
КонецФункции良い:
// 常にリンクを返します。空のリンク=見つかりませんでした。
Функция НайтиКонтрагентаПоИНН(ИНН)
Запрос = Новый Запрос("...");
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат Справочники.Контрагенты.ПустаяСсылка();
КонецЕсли;
Возврат Результат.Выгрузить()[0].Контрагент;
КонецФункцииコメント:「何」ではなく「なぜ」を説明してください
良いコードはほとんどコメントを必要としません。わかりやすい名前で説明しています。しかし、時にはコメントが必要です。たとえば、明白でないビジネスルールや、標準的でないソリューションの理由を説明する必要がある場合です。
役に立たないコメント:
// 日付を取得しています
Дата = ТекущаяДата();役立つコメント:
// 料金が次の月の初めの日付を使用するため
// 最初の日に更新され、請求は新しい価格で計算される必要があります
ДатаРасчёта = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), 1));エクスポート関数の場合は、必ずパラメータと戻り値の説明を追加してください。これは形式的なものではありません。これはAPIのドキュメントです。
// エリアと重量を考慮して送料を計算します。
// // パラメータ:
// 配達先住所 - 行 - FIAS形式の完全な住所
// 重量グラム - 数字 - 発送重量(グラム)
// // 戻り値:
// 数字 - 配送料金(ルーブル)、配送無料の場合は 0
// 関数 CalculateShippingCost (ShippingAddress, WeightGrams) エクスポートプログラミングの知識を深め、最新テクノロジーを学びたい場合は、アプリケーションをご覧ください コディックこれは、Python、JavaScript、HTML、CSS、その他の言語のコースを提供する教育プラットフォームです。複雑な内容をわかりやすい言葉で説明し、理論と実践を同時に学ぶことができます。
そして私たちの Telegramチャンネル 2000人以上の開発者からなるフレンドリーなコミュニティがあなたを待っています。いつでも質問をしたり、サポートを受けたり、志を同じくする人を見つけたりできます。 参加する — 一緒に仕事で成長する方がずっと簡単です!
