153 okumalar

Code Smell 304: Null Pointer istisnası - Çalışma Zamanı çökmesine neden olan NULL referanslarını nasıl önleyebilirim

ile Maximiliano Contieri9m2025/06/20
Read on Terminal Reader

Çok uzun; Okumak

Doğru doğrulama ve null-safe desenleri kullanarak çalıştırma zamanının çökmesine neden olan NULL referanslarını önleyin
featured image - Code Smell 304: Null Pointer istisnası - Çalışma Zamanı çökmesine neden olan NULL referanslarını nasıl önleyebilirim
Maximiliano Contieri HackerNoon profile picture

NULL sorunları hakkında yazmaya devam ediyorum, ancak her gün haber bana hatırlatıyor: NULL hala yaşıyor ve atıyor.


TL;DR: Doğru doğrulama ve null-safe desenleri kullanarak çalıştırma zamanının çökmesine neden olan NULL referanslarını önleyin

TL;DR: Doğru doğrulama ve null-safe desenleri kullanarak çalıştırma zamanının çökmesine neden olan NULL referanslarını önleyin

Sorunlar

  • Runtime Çatışması
  • Büyük olaylar ve kesintiler
  • Unpredictable behavior
  • Ağır Debugging
  • Kullanıcı frustrasyonu
  • Sistemin istikrarı
  • Kötü güvenilirlik

içindeGoogle Bulutİlişki :

  • Kötü hata yönetimi: Null verileri nazik bir şekilde işlemek yerine kod çöktü
  • Hiçbir özellik bayrakları: Güvenlik kontrolleri ile yeni kod yavaş yavaş yayılmadı
  • Anlık küresel replika: Kötü veriler Crowdstrike Olayı gibi hemen dünya çapında yayılıyor
  • Hiçbir rastgele geri dönüş yok: Kurtarma altyapının aşırı yüküne neden oldu
  • Yetersiz test: Başarısızlık senaryosu kurulum sırasında hiçbir zaman test edilmedi

Çözümler

  1. sıfırdan kaçınmak
  2. Null kontrollerini kullanın, eğer nulller kontrolünüzün dışında (örneğin, harici bir API)
  3. Başlangıç Default Values
  4. Gardiyan Sözleşmelerinin Uygulanması
  5. Null nesneleri kullanın
  6. Seçenekleri kullanmayın

Geri Dönüşüm ️

https://hackernoon.com/code-refactoring-tips-no-015-remove-null

bağlamı

12 Haziran 2015 ABüyük kesintilerGoogle Cloud Platform’da gerçekleşti.


Google Cloud ve Google Workspace hizmetlerini dünya çapında yaklaşık 10:49 AM'den 1:49 PM PDT'ye kadar etkiledi (3 saat toplam), bazı hizmetlerin tam olarak kurtarılması daha uzun sürdü.


Google’ın API yönetimi sisteminde bir arka planda arıza meydana geldi:


  • Trigger Hakkında:

29 Mayıs 2025'te Google, "Service Control" (API yönetim sistemi) için yeni bir kod dağıttı ve ek kvota politikası kontrollerini ekledi.


Bu kod kritik bir eksikliğe sahipti.Yanlış davranışve koruma altına alınmamıştıBayraklar Özellikleri.


  • Bu başarısızlık :

12 Haziran'da beyaz / beyaz içeren bir politika değişikliğisıfırService Control bu boş alanları işlemeye çalıştığında, korumasız kod yolunda bir null işaretleyici ile karşılaştı ve ikili opsiyonlar sonsuz bir döngüde çöktü.


  • Küresel Etkisi :

Kvota yönetimi küresel olduğu için, bu bozuk veriler saniyeler içinde dünya çapında çoğaltıldı ve Service Control her bölgede çöktü.


Null işaretleme istisnaları, var olmayan nesnelerin yöntemlerine veya özelliklerine erişmeye çalıştığınızda meydana gelir.


Bu, değişkenlerin geçerli nesne örneği yerine null referansları içerdiğinde gerçekleşir.


Sorun, bu istisnaların uygulamanızı çözebilebileceği ve kullanıcıları hayal kırıklığına uğratabileceği üretim ortamlarında özellikle tehlikeli hale gelir.


Java, C# ve JavaScript gibi diller özellikle bu soruna duyarlıdır, ancak modern dil özellikleri ve desenleri bu çöküşlerden tamamen kaçınmanıza yardımcı olabilir.


Nulller yıllardır yazılım endüstrisinde önemli bir sorun olmuştur, ancak yazılım mühendisleri, üreticilerinin uyarılarına rağmen bunları göz ardı etmeye devam etmektedir.

Kod örnekleri

Yanlış

public class ServiceControlPolicy {
  private SpannerDatabase spannerDB;
  private QuotaManager quotaManager;
    
  public void applyPolicyChange(PolicyChange change) {
      // NULL POINTER: change can be null
      Policy policy = spannerDB.getPolicy(change.getPolicyId());
      // NULL POINTER: policy can be null from the database
      String quotaField = policy.getQuotaField();
      // NULL POINTER: quotaField can be null (blank field)
      quotaManager.updateQuota(quotaField, change.getValue());
  }
    
  public void exerciseQuotaChecks(String region) {
      // NULL POINTER: policies list can be null
      List<Policy> policies = spannerDB.getPoliciesForRegion(region);
      for (Policy policy : policies) {
          // NULL POINTER: individual policy can be null
          String quotaValue = policy.getQuotaField();
          // NULL POINTER: quotaValue can be null before trim()
          quotaManager.checkQuota(quotaValue.trim());
      }
  }
    
  public boolean validatePolicyData(Policy policy) {
      // NULL POINTER: policy parameter can be null
      String quotaField = policy.getQuotaField();
      // NULL POINTER: quotaField can be null before length()
      return quotaField.length() > 0 && 
             !quotaField.equals("null");
  }
    
  public void replicateGlobally(PolicyChange change) {
      List<String> regions = getGlobalRegions();
      for (String region : regions) {
          // NULL POINTER: change.getPolicy() can return null
          spannerDB.insertPolicy(region, change.getPolicy());
      }
  }
}

Doğru

public class ServiceControlPolicy {
  private SpannerDatabase spannerDB;
  private QuotaManager quotaManager;
    
  public void applyPolicyChange(PolicyChange change) {
      if (change == null) {
          // Assuming it comes from an external API
          // Beyond your control
          change = new NullPolicyChange();
      }
      
      Policy policy = findPolicyOrNull(change.policyId());
      String quotaField = policy.quotaField();
      if (!quotaField.isEmpty()) {
          quotaManager.updateQuota(quotaField, change.value());
      }
  }
    
  public void exerciseQuotaChecks(String region) {
      if (region == null || region.isEmpty()) {
          // Assuming it comes from an external API
          // Beyond your control
          return;
      }
      
      List<Policy> policies = policiesOrEmpty(region);
      
      for (Policy policy : policies) {
          String quotaValue = policy.quotaField();
          if (!quotaValue.isEmpty()) {
              quotaManager.checkQuota(quotaValue.trim());
          }
      }
  }
    
  public boolean validatePolicyData(Policy policy) {
      if (policy == null) {
          // Assuming it comes from an external API
          // Beyond your control
          // From now on, you wrap it
          policy = new NullPolicy();
      }
      
      String quotaField = policy.quotaField();
      return quotaField.length() > 0;
  }
    
  public void replicateGlobally(PolicyChange change) {
      if (change == null) {
          // Assuming it comes from an external API
          // Beyond your control
          // From now on, you wrap it
          change = new NullPolicyChange();
      }
        
      Policy policy = change.policy();
      if (policy == null) {
          // Assuming it comes from an external API
          // Beyond your control
          // From now on, you wrap it
          policy = new NullPolicy();
      }
        
      List<String> regions = globalRegions();
      for (String region : regions) {
          spannerDB.insertPolicy(region, policy);
      }
  }
    
  private Policy findPolicyOrNull(String policyId) {
      Policy policy = spannerDB.policy(policyId);
      return policy != null ? policy : new NullPolicy();
  }
    
  private List<Policy> policiesOrEmpty(String region) {
      List<Policy> policies = spannerDB.policiesForRegion(region);
      if (policies == null) {
          // This is a good NullObject
          return Collections.emptyList();
      }
      
      return policies.stream()
              .map(p -> p != null ? p : new NullPolicy())
              .collect(Collectors.toList());
  }
}

class NullPolicy extends Policy {
  @Override
  public String quotaField() { return ""; }
    
  @Override
  public String policyId() { return "unknown-policy"; }
    
  @Override
  public Map<String, String> metadata() { 
      return Collections.emptyMap(); 
  }
}

class NullPolicyChange extends PolicyChange {
  @Override
  public String policyId() { return ""; }
    
  @Override
  public String value() { return ""; }
    
  @Override
  public Policy policy() { return new NullPolicy(); }
}

Keşifler

  • [x] Yarı otomatik

Null denetimi olmadan nesnelerdeki doğrudan metot çağrıları için kodları incelemekle potansiyel null işaretleme istisnaları tespit edebilirsiniz.


Linters, geri dönebilecek yöntemlerden geri dönüş değerlerini inceleyebilir.sıfır, başlangıçlanmamış nesne alanlarını arayın ve potansiyel null dereferences işareti statik analiz araçları kullanın.


Modern IDE’ler genellikle bu sorunları uyarılarla vurguluyor.

Güncel ️

  • sıfır

Seviye

  • [x] Ortaçağ

Neden bu kadar önemli ️

İçindeGerçek dünyaYani nesneler var ya da yok.


Bunu programınızda doğru bir şekilde modellediğinizde, net birTek Kişilik MektupGerçeklik ve kod arasında.


Null referanslara izin vererek bu bijeksiyonu kırmak, kodunuzda var olan ama gerçek dünyada olmayan hayalet nesneler oluşturur, bu var olmayan varlıklarla etkileşim kurmaya çalıştığınızda çöküşlere neden olur.


Eğer lisans panosunu "NULL" olarak adlandırmayı seçersenizÇok sayıda otopark bileti

Bu nesil

AI jeneratörleri sıklıkla null işaretleme hassasiyeti olan kodlar oluşturur, çünkü mutlu yol senaryolarına odaklanırlar.


Genellikle nesnelerin kullanılabileceği kenar durumları dikkate almadan metot çağrıları oluştururlar.sıfır, özellikle karmaşık nesne hiyerarşilerinde veya dış veri kaynaklarıyla uğraşırken.

Keşfedilecek Yerler

AI araçları, savunma programlama uygulamaları hakkında net talimatlar verdiğinizde null işaretçi sorunlarını tespit edebilir ve düzeltebilir.

Bunu deneyin!

Unutmayın: AI Asistanları Birçok Hata Yapar

Önerilen Prompt: Tüm null referansları kaldırmak

Önerilen Prompt: Tüm null referansları kaldırmak

Without Proper Instructions

With Specific Instructions

ChatGPT

ChatGPT

Claude

Claude

Perplexity

Perplexity

Copilot

Copilot

Gemini

Gemini

DeepSeek

DeepSeek

Meta AI

Meta AI

Grok

Grok

Qwen

Qwen

Çatışma

Çatışma

Claude için

Claude için

Şaşkınlık

Şaşkınlık

çocuk pilot

çocuk pilot

ikizler

ikizler

derinlemesine

derinlemesine

Hedefimiz AI

Hedefimiz AI

Gökçe

Grok

çin

çin

Sonuçlar

Null işaretleme istisnaları, programlamada en yaygın çalıştırma hatalarından biridir.


Uygun null kontrollerini uygulayarak, Null Object tasarım örneği kullanarak ve savunma programlama uygulamalarını uygulayarak bu düşüşlerin çoğunu ortadan kaldırabilirsiniz.


Validasyon kodunun küçüğü, uygulama istikrarı ve kullanıcı deneyimi açısından önemli ölçüde ödüyor.

İlişkiler

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iii-t7h3zkv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xliii

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxxix

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxvi

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xlii

Daha fazla bilgi

Disclaimer

Kokularım benimgörüşü.


Ben buna milyar dolarlık hatamı söylüyorum.1965 yılında null referansın icat edilmesiydi.

Ben buna milyar dolarlık hatamı söylüyorum.1965 yılında null referansın icat edilmesiydi.

Toni Şövalye


Bu makale CodeSmell serisinin bir parçasıdır.


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks