O‘zgaruvchi maydonlardan kelib chiqqan xatolar va ularning yechimi
Backend refaktoringi
1. Kirish — Maydon nomlari teskari saqlangan edi
So‘rov shablonini tahrirlovchi orqali ItemRule ro‘yxatga olinsa, frontend-da haqiqiy qoidalar kutilgandek ishlamaydi degan xato xabari keldi.
StateRule uchun “Agar ushbu element tanlansa, boshqa elementni yashir”deb qoidalar ro‘yxatiga olindi, ammo aslida teskari ishlash hodisasi ro‘y berdi. Dastlab, frontend shartlarni baholash mantiqiga shubha qildik.
Kodlarni kuzatganimizda muammo yanada asosiy joyda ekanligini aniqladik. Backend entitiyining maydon nomi o‘zining haqiqiy ma’nosiga teskari o‘rnatilgan edi.
|
java // Haqiqiy DBda saqlangan ma’lumotlarning ma’nosi (o‘zgartirishdan oldin) targetItemKey = "formId:Q3" // Haqiqiyda — trigger (manba) sourceItemKeys = ["formId:Q1"] // Haqiqiyda — ta’sir doirasi (maqsad) |
|---|
Trigger (qandaydir element o‘zgartirilganda) targetItemKey ga, ta’sir doirasi (qanday elementga qoidalarning tatbiq etilishini) esa sourceItemKeys ga saqlanmoqda. Nomi teskari turibdi, shuning uchun bu ma’lumotlarni o‘qiyotgan frontend chalkashlanishga duch keladi.
2. Muammo qanchalik chuqur tarqalgan edi
Oddiygina maydon nomini o‘zgartirish kerak kabi tuyulgan edi, ammo aslida bu muammo barcha qatlamlarda mavjud bo‘lgan.
|
# |
muammo |
ta'sir |
|---|---|---|
|
1 |
targetItemKey ↔ sourceItemKeys ma'nosi teskari |
yangi dasturchilarni chalkashtiradi, xatoliklarni keltirib chiqaradi |
|
2 |
CalculationRule'da sourceItemKeys maydoni yo'q |
manba izlab bo'lmaydi, bog'lanish tahlil qilinmaydi |
|
3 |
manba variables, aggregationTargets, conditions 3 joyga tarqalgan |
kod murakkabligi oshadi |
|
4 |
AggregationTarget Source+Condition aralash |
bir martalik mas'uliyat tamoyilini buzadi |
|
5 |
CDO → Entity o'zgartirishda sourceItemKeys yo'qolishi mumkinligi |
Ma'lumotlar to'g'rilik muammosi |
Bu oddiy nomlash muammosi emas edi. CalculationRule kerak bo'lgan kiritish manbasi bitta maydonga to'planmaganligi sababli, bog'liqlikni kuzatish va tasdiqlashning murakkab strukturasiga ega edi.
java
// CalculationRule 수정 전 — 소스를 어디서 찾아야 하는가?
private List<FormulaVariable> variables; // 여기도 소스
private List<AggregationTarget> aggregationTargets; // 여기도 소스
private List<EnableCondition> conditions; // 여기도 소스(조건 내 참조)
Manbalar 3 joyda tarqatilgan va AggregationTarget nomi to'plovchi maqsadmi yoki to'plovchi shartmi ekanligi ham aniq emas edi.
3. Qanday qilib o'zgartirdik
3-1. Maydon ma'nosini qayta belgilash
Eng avvalo qilinishi lozim bo'lgan ish sourceItemKeys nimani anglatishini qayta ta'riflash edi.
sourceItemKeys = 트리거 (어떤 항목이 변경될 때 규칙이 발동하는가)
targetItemKeys = 효과 대상 (규칙이 적용될 항목들)
StateRule misolida:
|
“I7 raqami o'zgarganda → I5, I6 raqamlarini yashir” sourceItemKeys: ["formId:Q3"] → triger targetItemKeys: ["formId:Q1", "formId:Q2"] → ta'sir doirasi |
|---|
3-2. Ta'sir doirasidagi barcha darajalarni o'zgartirish
Bu ta'rifga asoslanib Entity, CDO, JPO, Store, Helper, RDO barcha darajalarini o'zgartirdik.
|
Domain Entity → sourceItemKeys(triger), targetItemKeys(ta'sir doirasi) qayta ta'riflash CDO → StateRuleCdo, CalculationRuleCdo field tuzilishini toʻgʻirlash JPO → DB ustun xaritalashini tuzatish Store → saqlash/qidirish mantiqi muvofiqligini tekshirish RDO → frontend javob tuzilishi dual-output qoʻllanishi |
|---|
3-3. AggregationTarget → CalcSourceGroup nomlari tartibga solish
AggregationTarget nomi Source va Conditionning aralash vazifasini bajarayotgandi. Har bir maydonning asl vazifasini aniq belgilab, CalcSourceGroup bilan almashtirdik.
java
// 수정 전
class AggregationTarget {
List<String> sourceKeys;
String conditionItemKey; // Source인가 Condition인가?
List<String> contextRelatedKeys;
}
// 수정 후
class CalcSourceGroup {
List<String> sourceKeys; // 계산할 실제 값의 출처 (순수 Source)
@JsonProperty("conditionItemKey") // JSON 키 하위호환 유지
String filterConditionKey; // 이 그룹의 필터 조건 (Condition)
List<String> contextRelatedKeys; // 의존성 맥락 출처
}
@JsonProperty("conditionItemKey") yordamida JSON simli kaliti saqlanib, mavjud ma'lumotlar ostidagi moslikni ta'minladi.
4. DB migratsiya loyihasi
Kod o'zgarsa ham, eski DB ma'lumotlari o'zgarishlarsiz qolmoqda. Tarqatish bilan birga ma'lumotlarni ham to'g'rilash kerak edi.
STATE holatidaikki qadamning tartibi muhim.Avvalo, eski source_item_keys ni yangi target_item_keys ga nusxalab olamiz, so'ngra target_item_key ni yangi source_item_keys ga o'tkazishimiz kerak. Tartib o'zgarsa, asl ma'lumot ustiga yoziladi.
sql
BEGIN;
-- Step 1: 기존 효과 대상(source_item_keys) → 새 효과 대상(target_item_keys)
UPDATE item_rule
SET target_item_keys = COALESCE(source_item_keys, '[]'::jsonb)
WHERE rule_type = 'STATE';
-- Step 2: 기존 트리거(target_item_key) → 새 트리거(source_item_keys)
UPDATE item_rule
SET source_item_keys = CASE
WHEN target_item_key IS NULL OR target_item_key = '' THEN '[]'::jsonb
ELSE jsonb_build_array(target_item_key)
END
WHERE rule_type = 'STATE';
COMMIT;
CALCULATION holatida source_item_keys umuman mavjud bo'lmagan maydon edi, variables va aggregation_targets ga tarqatilgan manba kalitlarini chiqarib, qayta normalizatsiya orqali to'ldirdik.
sql
-- variables.sourceKey + aggregation_targets[].sourceKeys 에서 중복 제거 후 통합
UPDATE item_rule AS c
SET source_item_keys = sub.keys
FROM (
SELECT r.id,
to_jsonb(ARRAY(
SELECT DISTINCT k FROM (
SELECT v->>'sourceKey' AS k
FROM jsonb_array_elements(COALESCE(r.variables, '[]')) v
UNION ALL
SELECT sk#>>'{}' AS k
FROM jsonb_array_elements(COALESCE(r.aggregation_targets, '[]')) agt,
jsonb_array_elements(COALESCE(agt->'sourceKeys', '[]')) sk
) all_keys WHERE k IS NOT NULL AND k <> ''
)) AS keys
FROM item_rule r
WHERE r.rule_type = 'CALCULATION'
AND (r.source_item_keys IS NULL OR r.source_item_keys = '[]')
) sub
WHERE c.id = sub.id;
5. Xulosa qilib
Ushbu refaktoringning asosiy maqsadi faqat nomlarni to'g'irlashda emas edi.
Oʻzgartirilgan maydon maʼnolarini domen, API, DB, javob modeli bo‘yicha izchil standartlarga qayta tartibga keltirib, mavjud maʼlumotlar va front-end mosligini saqlagan holda ishonchli ravishda tarqatish muhim vazifa bo‘ldi.
Natijada StateRule sourceItemKeys=triger, targetItemKeys=ta'sir qilingan obyekt degan ma'noni aniq qilib ko'rsatdi va CalculationRule ham sourceItemKeys va calcSourceGroups atrofida kirish manbalarini yanada aniqroq kuzatish mumkin bo'lgan tuzilma bilan tartibga solindi.
Eng muhimi, bu ish faqat bitta maydon nomini o'zgartirish emas, balki uzoq vaqt davomida to'plangan talqin chalkashligini tartibga solish va keyinchalik qoidalar funksiyasini yanada xavfsizroq kengaytirish uchun asos yaratish edi.
Justin