Statik analiz aracınız bir koşulu her zaman yanlış olarak işaretledi. Uyarı, kullandığınız araca bağlı olarak şunlardan birine benzeyebilir:
- SonarQube: "Her zaman doğru veya yanlış olan koşullu ifadeler, erişilemeyen kodlara yol açabilir." (RSPEC-2583)
- IntelliJ / Inspectopedia: "Koşul statik olarak yanlış olarak değerlendirildiği için kod analiz edilmiyor."
- Checkmarx / Fortify: “Erişilemeyen kod, ölü dal tespit edildi”
- ESLint: “sabit koşul yok, beklenmedik sabit koşul”
- Pilint: “W0125: Sabit değere sahip koşullu bir ifade kullanma”
Bütün bunlar aynı şeyi söylüyor: analiz aracı, kodu çalıştırmadan, analiz sırasında, koşullu bir ifadenin belirli bir dalının asla yürütülemeyeceğini kanıtladı. Bu dalı koruyan koşul her zaman yanlıştır. Bu dalın içindeki her şey ölü koddur.
Bu kılavuz, bu uyarıların nedenlerini, her bir uyarının hangi kategoriye girdiğini belirlemeyi, her kategori için doğru çözümü, bastırmanın ne zaman uygun olduğunu ve eski COBOL kodundaki her zaman yanlış olan koşulların geçiş kapsamı hakkında neler ortaya koyduğunu ele almaktadır.
Kullanımdan kaldırılmış iş kuralları hâlâ kodunuzda mevcut.
SMART TS XL Üretim verilerinde artık mevcut olmayan ürün kodlarına, durum değerlerine ve müşteri türlerine atıfta bulunan DEĞERLENDİRME dallarını tanımlar.
DAHA FAZLASINI ÖĞRENİN…Statik Analiz Her Zaman Yanlış Olan Koşulları Nasıl Tespit Eder?
Modern statik analizciler, her zaman yanlış olan koşulları tespit etmek için basit kalıp eşleştirmesi yerine sembolik yürütme ve veri akışı analizini kullanır. Analizci, programın her noktasında her değişkenin olası değerlerini izler. Bir koşula ulaştığında, değişkenler üzerindeki bilinen kısıtlamalar göz önüne alındığında, koşulun hiçbir zaman doğru olup olamayacağını değerlendirir.
Her zaman yanlış sonuç veren tespitlere yol açan üç temel mekanizma vardır:
Sembolik infaz. Analizleyici, değişkenlere sembolik değerler atar ve işlemlerin bu değerleri nasıl kısıtladığını izler. Eğer değişken x atandı 0 3. satırda ve karşılaştırıldı x > 10 7. satırda araya giren herhangi bir atama işlemi yoksa, koşulun yanlış olduğu kanıtlanabilir.
Tip sistemi kısıtlamaları. Değişkenin türü göz önüne alındığında bazı koşullar imkansızdır. Boş olmayan bir nesne referansının, boş olmayan bir doğrulama sonrasında boş değerle karşılaştırılması veya bir enum değerinin tanımlı kümesinin dışındaki bir durumla karşılaştırılması.
Boolean cebirinin basitleştirilmesi. Basitleştirildiğinde karmaşık hale gelen durumlar false Değişken değerlerinden bağımsız olarak: (a && !a), (x > 10 && x < 5), (!flag || false).
SonarQube'un RSPEC-2583 kuralı özellikle sembolik yürütmeyi kullanır: kontrol akış grafiği boyunca değişkenlerin durumunu izler ve sembolik durumun koşulu kanıtlanabilir şekilde yanlış kıldığı durumları işaretler. IntelliJ'nin "koşul statik olarak yanlış olarak değerlendirildi" uyarısı da aynı yaklaşımı kullanır.
Dört Temel Neden
Sürekli yanlış olan bir uyarıyı doğru şekilde çözmek, dört temel nedenden hangisinin geçerli olduğunu doğru bir şekilde belirlemeye bağlıdır. Çözüm her biri için farklıdır.
Temel Sebep 1: Mantıksal Çelişki
Bu koşul mantıksal bir imkansızlık, aynı anda doğru olamayacak iki alt koşul veya şu sonuca indirgenebilen bileşik bir koşul içermektedir: false Boolean cebiri ile.
Java
// Example: mutually exclusive subconditions
int score = getScore();
if (score > 90 && score < 50) { // Always false: no integer is both > 90 and < 50
applyBonus(); // Never executes
}
// Example: boolean tautology negation
boolean active = isActive();
if (active && !active) { // Always false: a && !a = false
sendNotification(); // Never executes
}
// Example: range check already guaranteed
if (value >= 0) {
if (value < 0) { // Always false: already know value >= 0
handleNegative(); // Never executes
}
}
Çözüm: Mantığı düzeltin. Ya koşulda bir yazım hatası var (geliştirici şunu kastetmiş olabilir): score > 90 || score < 50) veya dal kaldırılmalıdır. Aralık kontrolü örneğinde, içteki if Gereksizdir ve silinmelidir.
Temel Sebep 2: Birikmiş İş Kuralı Değişiklikleri
Bu, uzun ömürlü kod tabanlarındaki en önemli nedendir. Yazıldığı sırada geçerli ve anlamlı olan bir koşul, etrafındaki kodda yapılan sonraki değişiklikler nedeniyle kalıcı olarak yanlış hale gelmiştir ve artık çalışmayan dal kaldırılmamıştır.
Java
// 2018: processType could be A, B, or C
// 2023: type C was deprecated and removed from the system
// The processType field is now guaranteed to never equal "C"
// but nobody removed the branch that handled it
public void process(String processType) {
if (processType.equals("A")) {
handleTypeA();
} else if (processType.equals("B")) {
handleTypeB();
} else if (processType.equals("C")) { // Always false since 2023
handleTypeC(); // 47 lines of dead business logic
}
}
piton
# Python equivalent: accumulated rule changes
def calculate_rate(customer_tier: str) -> float:
if customer_tier == "GOLD":
return 0.05
elif customer_tier == "SILVER":
return 0.03
elif customer_tier == "BRONZE":
# BRONZE tier was eliminated in Q2 2021
# All BRONZE customers were migrated to SILVER
# This branch has been dead for 4+ years
return 0.01 # Never executes
return 0.0
Çözüm: İş bağlamını doğrulayın, ardından ölü dalı tamamen kaldırın. Koşulu mümkün kılan iş kuralı değişti. Bunu uygulayan kod artık gerekli değil. Kaldırma işlemini taahhüt mesajında belgeleyin: “BRONZ oranlı dal kaldırıldı, kademe 2021'in 2. çeyreğinde ortadan kaldırıldı, tüm müşteriler GÜMÜŞ'e geçti.”
Temel Sebep 3: Geleceğe Hazırlık İçin Savunmacı Programlama
Bazı her zaman yanlış olan koşullar kasıtlıdır; geliştirici, koşulun şu anda doğru olamayacağını bilerek, gelecekteki kod değişikliklerinin onu doğru hale getirme olasılığına karşı bir önlem olarak bunları yazmıştır.
Java
// SonarQube RSPEC-2583 explicitly exempts these:
final boolean DEBUG_MODE = false;
if (DEBUG_MODE) { // Always false -- intentional
dumpDiagnostics(); // Not unreachable in intent, only in fact
}
// Type narrowing that appears redundant
String value = getValue();
if (value == null || value.isEmpty()) {
return;
}
// At this point, static analysis knows value is non-null and non-empty
if (value == null) { // Always false -- already checked above
throw new IllegalStateException(); // Defensive guard
}
SonarQube RSPEC-2583, açıkça bir istisna belirler: "Koşul tek bir nihai boolean değer olduğunda" veya "koşul tam anlamıyla doğru veya yanlış olduğunda", bunlar kasıtlı olarak ele alınır ve işaretlenmez.
Çözüm: Eğer koşul bir hata ayıklama bayrağı veya derleme zamanı sabiti ise: olduğu gibi bırakın ve araç bunu işaretlerse bir bastırma ek açıklaması ekleyin. Eğer gereksiz gibi görünen ancak gerçekten koruyucu olan savunma amaçlı bir boş değer kontrolü veya aralık koruması ise: korumayı farklı bir seviyede açıkça belirtmek için kodu yeniden yapılandırın veya belgelenmiş bir gerekçeyle bastırın.
4. Temel Sebep: Çalışma Zamanı Yapılandırmasından Kaynaklanan Araç Yanlış Pozitif Sonuçları
Statik analizciler çalışma zamanı yapılandırmasını, ortam değişkenlerini, yansımayı, ek açıklama işlemeyi veya bağımlılık enjeksiyonunu göremez. Analizciye her zaman yanlış görünen kod, analizcinin modelleyemediği bir çalışma zamanı mekanizması aracılığıyla erişilebilir olabilir.
Java
// IntelliJ / Inspectopedia note: "This may cause false-positives if any kind
// of code postprocessing is used, for example, if an annotation processor
// later replaces the method body with something useful."
@ConditionalOnProperty(name = "feature.experimental", havingValue = "true")
public class ExperimentalFeature {
// This class may appear unreachable if the property is false in the
// test configuration the analyzer uses -- but it IS reachable in prod
}
// Method contract that the analyzer cannot see
void run() {
performAction();
System.out.println("Done"); // IntelliJ flags as unreachable
}
@Contract("-> _") // Tells the analyzer: method does NOT always throw
static void performAction() { throw new AssertionError(); }
Çözüm: Uygun yöntem sözleşmesi açıklamasını ekleyin (@Contract IntelliJ için, @NotNull/@Nullable Kotlin için tür doğrulamaları, TypeScript için tür onaylamaları gibi ek açıklamalar, çözümleyiciye ihtiyaç duyduğu çalışma zamanı bilgilerini sağlar. Ek açıklama tabanlı çözümleme mevcut değilse, belgelenmiş bir gerekçeyle aracın bastırma mekanizmasını kullanın.
COBOL: Her Zaman Yanlış Olan Koşulların Onlarca Yıllık Ölü Mantığı Ortaya Çıkardığı Yer
COBOL ve eski ana bilgisayar sistemlerinde, her zaman yanlış olan koşullar, modern uygulama kodundakilerden farklı bir karaktere ve bunları sürdüren veya modernize eden ekipler için farklı bir öneme sahiptir.
COBOL programları, modern kodlardaki gibi yeniden yapılandırılmaz. Bir iş kuralı değiştiğinde, bir vergi kodu revize edildiğinde, bir ürün kademesi ortadan kaldırıldığında, bir düzenleyici gereklilik güncellendiğinde, yaygın uygulama eski mantığı kaldırmadan yeni mantığı eklemektir. Eski EVALUATE WHEN veya IF dalı, işlediği verilerin mevcut durumuna göre asla doğru olamayacak bir koşulla korunarak kaynak kodda kalır.
COBOL
EVALUATE WS-PRODUCT-TYPE
WHEN 'STD'
PERFORM CALC-STANDARD-RATE
WHEN 'PRM'
PERFORM CALC-PREMIUM-RATE
WHEN 'BAS'
* BAS product type retired June 2009
* All BAS customers converted to STD
* This branch has been dead for 15+ years
PERFORM CALC-BASIC-RATE
WHEN 'LEG'
* LEG (legacy) type eliminated in 2001 system migration
* Should have been removed but was left as "just in case"
PERFORM CALC-LEGACY-RATE
WHEN OTHER
PERFORM HANDLE-UNKNOWN-TYPE
END-EVALUATE.
Bu DEĞERLENDİRME'deki iki ölü dal, BAS hem de LEGBunlar hata değil. Bunlar tarihsel kalıntılar: sistemin tarihindeki belirli noktalarda geçerli olan ve bu ürün türleri kullanımdan kaldırıldığında kalıcı olarak erişilemez hale gelen iş kuralları. Kimse onları kaldırmadı çünkü hala gerekli olup olmadıklarından emin değildi ve yanılmanın maliyeti, onları yerinde bırakmanın maliyetinden daha yüksek görünüyordu.
COBOL'da her zaman yanlış olan koşulların ortaya koyduğu şey:
Ölü dallar, artık geçerli olmayan iş mantığını temsil eder. PERFORM CALC-BASIC-RATE hem de PERFORM CALC-LEGACY-RATE Hedefler, kendileri de benzer şekilde ölü olan, potansiyel olarak her biri yüzlerce satırdan oluşan, COBOL kodunun tamamı paragrafları veya bölümleri olabilir. Her zaman yanlış olan koşul, PERFORM ilişkileri aracılığıyla yayılan ölü kod ağacının giriş noktasıdır.
100,000 satırlık bir COBOL programında, kullanım dışı bırakılan iş kurallarından kaynaklanan ölü dallar, toplam kodun %20-35'ini oluşturabilir. Bu yüzde, modernizasyon programında dönüştürülmesi, test edilmesi veya doğrulanması gerekmeyen geçiş kapsamını temsil eder. Geçiş planlamasından önce bunun belirlenmesi, doğrudan kapsam azaltımına yol açar ve planlama aşamasında kapsam azaltımı, her zaman yanlış koşul analizinin en yüksek değerli uygulamasıdır.
Çözüm Karar Ağacı
Always-false condition warning received
│
▼
Is this a compile-time constant
or debug flag? (DEBUG = false, etc.)
│
Yes ───┼─── No
│ │
Intentional. ▼
Suppress or Does the condition
leave as-is. contain a logic error?
(a > 10 && a < 5, etc.)
│
Yes ───┼─── No
│ │
Fix the Has the condition
logic bug. become false due to
a past business rule
change?
│
Yes ───┼─── No
│ │
Verify, Could a runtime
then remove mechanism make
the dead it reachable?
branch. │
Yes ──── No
│
Add contract
annotation. Remove the
dead branch.
Baskılama: Ne Zaman ve Nasıl
Durumun gerçekten kasıtlı olduğu ve ilgili kişiye nedenini anlamak için sözleşme bilgileri verilemediği durumlarda, uyarıyı gizlemek uygundur. Ancak, uyarının gerçekte ne anlama geldiğini araştırmaktan kaçınmak için kestirme yol olarak kullanmak uygun değildir.
Java (SonarQube):
Java
@SuppressWarnings("java:S2583")
if (DEBUG_MODE) { // Intentional: compile-time debug flag
dumpState();
}
Java (IntelliJ):
Java
//noinspection ConstantConditions
if (possiblyNull != null) { // Analyzer cannot see the runtime injection
process(possiblyNull);
}
Python (Pylint):
piton
if False: # pylint: disable=W0125
# Intentional: placeholder for future implementation
pass
C# (SonarQube):
csharp
#pragma warning disable S2589
if (IsDebugBuild) { // Compile-time constant -- intentional
LogDiagnostics();
}
#pragma warning restore S2589
KOBOL (SMART TS XL / özel bastırma yorumu):
COBOL
*>> SUPPRESS UNREACHABLE: BAS branch retained for audit trail
WHEN 'BAS'
PERFORM CALC-BASIC-RATE
Bastırma disiplini: Her sansürleme işlemine, sadece sansürlendiğini belirtmekle kalmayıp, durumun neden kasıtlı olduğunu açıklayan bir yorum eşlik etmelidir. Sansürleme yorumu şu şekilde olmalıdır:
// suppress unreachableHiçbir baskılama olmamasından daha kötüdür; uyarıyı neden yanlış olduğunu açıklamadan gizler. Bir baskılama ise şunu söyler:// suppress: DEBUG_MODE is a compile-time constant, branch is retained for IDE visibilitykabul edilebilir.
Ne kadar SMART TS XL Portföy ölçeğinde her zaman yanlış olan koşulları belirler.
SMART TS XL'S statik kod analizi Bu yöntem, COBOL, JCL, Java, Python ve ortamdaki diğer tüm dillerde veri akışı ve kontrol akışı analizini uygulayarak, portföy ölçeğinde, binlerce programda aynı anda, her zaman yanlış olduğu statik olarak kanıtlanabilir koşulları belirler; bunu bir geliştirici IDE'sinde tek tek dosyalar üzerinde değil, tüm program üzerinde yapar.
Özellikle COBOL portföyleri için bu şu anlama gelir: Her programdaki her EVALUATE WHEN maddesi ve her IF koşulu, içine akan veriler üzerindeki bilinen kısıtlamalara göre analiz edilir. Programın geçmişi boyunca geçerli değer kümeleri değişen ürün kodlarına, durum bayraklarına veya tür kodlarına atıfta bulunan koşullar, potansiyel ölü dallar olarak işaretlenir. Çıktı, bir ölü kod envanteridir: her program, her ölü dal ve her zaman yanlış olan koşuldan erişilebilen tahmini ölü kod satır sayısı.
Eski sistem modernizasyon analizi, bu envanteri kapsam azaltımına dönüştürür: herhangi bir dönüştürme çabası başlamadan önce, ölü tüm dallar geçiş spesifikasyonundan çıkarılır. 2,000 satır iş mantığına sahip gibi görünen bir program, kullanımdan kaldırılmış ürün türlerinden, ortadan kaldırılmış müşteri kademelerinden ve kullanımdan kaldırılmış hesaplama yollarından kaynaklanan 600 satır ölü iş mantığına sahip olabilir. 2,000 satır yerine 1,400 satır geçirmek, bu programda %30'luk bir kapsam azaltımı anlamına gelir ve ölü dallar, geçiş için en yüksek riskli kapsam parçasıdır, çünkü bunların ilk etapta ne işe yaradıkları bilinmemektedir.
Kurumsal arama özelliği, her zaman yanlış olan envanteri sorgulanabilir hale getirir: mevcut ürün kataloğunda olmayan bir ürün koduna atıfta bulunan bir EVALUATE WHEN yan tümcesi içeren her COBOL programını, belirli bir yıldan beri veritabanında bulunmayan bir durum bayrağı değerini kontrol eden her programı, koşul yazıldıktan sonra yeniden kullanılan bir veri yapısı alanına atıfta bulunan her IF koşulunu bulun. Bu sorgular, büyük bir COBOL portföyünde manuel kod incelemesinin aylar süreceği hedefli ölü kod envanterini üretir.
Uyarı genellikle doğrudur.
Statik analiz uyarıları, her zaman yanlış olan koşullar için çoğu durumda doğru bulgulardır. Koşul her zaman yanlıştır. Dal asla çalışmaz. İçindeki kod ölüdür.
Uygun yanıt bastırma değil, araştırma olmalıdır. Hangi temel neden geçerlidir? Mantıksal çelişki, birikmiş iş kuralı değişikliği, kasıtlı savunmacı programlama veya çalışma zamanı yapılandırmasından kaynaklanan araç yanlış pozitif sonucu? Her birinin doğru bir çözümü vardır. Dördünden üçü ölü kodun kaldırılmasıyla sonuçlanır. Biri ise gerekçeli olarak bastırmayla sonuçlanır.
Eski COBOL sistemleri için, portföy ölçeğinde her zaman yanlış olan durum analizi öncelikle bir kod kalitesi çalışması değil, bir kapsam azaltma çalışmasıdır. On yıllarca süren iş kuralı değişiklikleri sonucunda biriken ölü dallar, taahhüt edilmemesi gereken bir geçiş çabasını temsil eder. Geçiş planı kilitlenmeden önce bunları bulmak, bir COBOL modernizasyon programı planlayan herhangi bir ekip için her zaman yanlış olan durum analizinin en değerli uygulamasıdır.
Analiz cihazı size doğru bir şey söylüyor. Ona kulak verin.


