IPv4 Adres Formatlama Üzerinden Temiz Kod Örneği

İbrahim Kürce
3 min readApr 8, 2020

İşimin parçası olarak bu aralar IP adresleri üzerine çalışıyorum. Onunla ilgili denemeler yaparken, güzel bir temiz kod örneği anlatabilirim diye bu yazıyı yazmaya karar verdim. Haydi bismillah.

Sorunum şu idi; String olarak bir IP adresini input olarak alacağım ve bunu bir artırıp yine uygun formatta String olarak geri döneceğim. Mesela, 10.0.0.1 gibi bir input aldığımızda geriye 10.0.0.2 döneceğim. Evet bu kadar basit!

Cevap tabi ki bu kadar basit değildi ama çok da zor değildi. Bit üzerine yapılan işlemleri biraz hatırlamam gerekiyordu. Java ile kodlayacaktım ve Java’nın Integer değerleri üzerinde binary(ikili taban) işlem yapma desteği vardı. İlk önce Integer değerleri ile ikili tabanda işlem yapmak istedim. Integer en fazla 32 bit değer aldığı için IPv4 için belki beni kurtarabilirdi ama IPv6(128 bit) ile çalışmaya başladığımda bu bana yetmeyecekti. BitSet kullanabileceğim bir diğer alternatifti. Ben daha kolayıma gittiği için BigInteger sınıfından yararlanarak sonuca ulaştım. Belki ilerde BitSet kullanarak da çözebilirim. Kodlamaya başlayalım ufaktan.

Öncelikle kendime ufak bir test kümesi hazırladım. Bu benim işimi çok kolaylaştıracak. Kod adım adım gelişmeye devam ettikçe, bu test kümesini her seferinde çalıştıracağım. Aslında bu durumda Test kütüphanelerini kullanırız ama ben daha basit olsun diye bir karşılaştırma ile yetineceğim.

Uygun gelen IP adreslerinde doğru değer dönmesini beklerken, uygun olmayan değerlerde basitlik adına hata fırlatıp null değer döneceğim.

İlk olarak kodumu çalışabilir hale getirene kadar tek bir metod üzerinde çalışacağım. Aralara bilgilendirici Log’lar ekleyeceğim. İsimlendirmelere çok takılmayacağım. Çalışır duruma geldikten sonra bu logları silip, daha sonra anlamlı alt metodlara böleceğim ve güzel isimlendirmeler vermeye çalışacağım.

İlk önce yapmamız gereken şey, IPv4 adresi 4 bölümden oluştuğu ve her bölüm nokta ile ayrıldığı için, nokta(.) karakterine göre ayırmak olacaktır.

Sonra da bunları ikili format haline getirip art arda bir araya getireceğim. Elimizde 32 bitlik 1'ler ve 0'lardan oluşan bir String olacak. Bunu yaparken her bölüm için 8 bit olması için padding ekleriz. Yani 0 diye bir bölümümüz var ise 00000000(8 tane sıfır) olacak şekilde bir araya getireceğiz. Buraya kadar olan koda bakalım.

Buraya kadar olan kodu çalıştırırsak, şöyle çıktı alırız.

İlk değer:  255.255.255.1
İkili hali: 11111111111111111111111100000001

Daha sonra IP adresinin ikili olarak değerini 1 artırırız. İlk önce elimizdeki ikili haldeki String değeri BigInteger sınıfının radix değerini 2 kullanarak tekrar BigInteger sınıfına çeviririz. Burada radix değerini belirtmek önemli, yoksa aritmetik işlemi onluk tabana göre yapar.

Artırma işleminden sonra 32 bit olacak şekilde tekrar padding uygularız.

Buraya kadar olan kodun çıktısına bakalım.

İlk değer:   255.255.255.1
İkili hali: 11111111111111111111111100000001
Bir fazlası: 11111111111111111111111100000010

Evet sondaki 01 bitleri artırarak 10 haline getirmiş. Doğru gidiyoruz demektir.

Daha sonra bu 32 bitlik değeri 8'li olarak 4 parçaya ayırıp 10'luk tabana çevireceğiz. Bunun çok farklı yolu var ama ben String sınıfının substring metodundan yararlanacağım. Bir while döngüsü içinde 8'li olarak sonuna kadar böleceğim. 32 bit olduğundan bunu 4 kere yapmasını bekliyorum.

Bu kodumuzun çıktısı da şöyle olur. Her bölüm için hem ikili değerini hem de ondalık değerini yazdırdık. Sıkıntı gözükmüyor.

İlk değer:   255.255.255.1
İkili hali: 11111111111111111111111100000001
Bir fazlası: 11111111111111111111111100000010
Bölüm 1: 11111111–255
Bölüm 2: 11111111–255
Bölüm 3: 11111111–255
Bölüm 4: 00000010–2

Gelelim bu ondalık değerleri tekrar nokta(.) ile birleştirmeye. Son bölüm hariç nokta ile birleştireceğiz.

Bu kodumuzun da çıktısı şöyle olur. Son değerimizi elde etmiş olduk.

İlk değer:   255.255.255.1
İkili hali: 11111111111111111111111100000001
Bir fazlası: 11111111111111111111111100000010
Bölüm 1: 11111111–255
Bölüm 2: 11111111–255
Bölüm 3: 11111111–255
Bölüm 4: 00000010–2
Son değer: 255.255.255.2

Çalışan kodumuza ulaşmış olduk. Sıkıcı kısım bitmiş oldu, artık eğlenceli kısma geçelim :) Kodumuzu yeniden düzenlemeye(refactor) başlayalım.

IP adresi String’ten parçalayıp, sonra ikili olarak tekrar bir araya getiren kısmı getBinary olarak ayrı bir metoda çıkaralım.

Bundan sonra adım adım metodlara bölme(extract method) ile tek parça olan kodu, parçalara ayıralım. Kodu kesmekten korkmayın, kesebildiğiniz kadar kesin.

Artırma işlemini, IP adreslerin kısımlarını ve formatlama işlerini de ayrı metodlara çıkaralım. Kodda tanımladığımız 2, 8, 32 gibi sihirli sayılardan(magic numbers) kurtulup, bunları final değişkenlere taşıyalım.

Kodumuzu yeniden düzenlersek son hali şöyle olur.

Şimdi neler yaptığımıza madde madde bakalım.

  1. Kodumuzu anlamlı, anlaşılır küçük parçalara böldük, genelde 10 satır altında tuttuk. Satır sayısı şart olmasa da küçük metod her zaman daha anlaşılır diyebiliriz.
  2. Değişken adlarını güzelleştirdik, anlamlı isimler verdik.
  3. Sihirli sayılardan kurtulduk, static final değişkenlere taşıdık. Anlamlı isimler verdik.
  4. İlkel de olsa format hatalarına karşı kontroller ekledik. Sonuçta yanlış input her zaman gelebilir değil mi?
  5. Gereksiz logları sildik, yorumlar yerine anlaşılır metod isimlendirmeleri yaptık. Biliyoruz ki, koddaki yorumlar bir süre sonra atıl kalacak, güncellenmeyecek. Bu da bize yanlış fikir verecek. Yanlış fikir vermesindense hiç olmaması daha iyidir.

Ana metodumuzun ne kadar küçük ve güzel olduğuna tekrar bakalım ve yazıyı bitirelim.

Virüsten uzak, sevdiklerinizle sağlıklı kalmanız dileğiyle…

--

--