Ruby Kod Parçacıkları - 14 (Module Kullanımı)

Merhaba arkadaşlar,

Module’leri sınıf değişkenleri, sınıflar, metodlar ve sabitleri(Constant) içerisinde barındırabilen isim alanları(namespace) olarak düşünebiliriz. Özellikle projelerin büyüdüğü durumlarda kullanılan tip veya metodların çakışmasını engellemek, kod tekrarlarının önüne geçmek(DRY-Don'r Repeat Yourself), bakım maliyetlerini azaltmak ve özellikle aynı iş alanına(Domain) özgü operasyonları anlamlı isim alanlarında konuşlandırabilmek maksadıyla tercih edilirler. 

Bununla birlikte Ruby dilinde bir tipin n sayıda tipten aynı anda türemesine izin verilmemesi söz konusudur. Yani bir tip tek bir diğer tipten türeyebilir. Bu yüzden modüller aynı seviyede çoklu kalıtımı(Multi-Inheritance) desteklemek amacıyla Mixin olarak da değerlendirilirler. 

Modüller çok doğal olarak örneklenemezler(Yani bir sınıf örneği oluşturur gibi modül örnekleri oluşturulamaz) Modüller arası kalıtım ve bu şekilde oluşan bir modül hiyerarşisi söz konusu değildir. İç içe modül geliştirilmesi ise mümkündür(Nested Modules). Modüllerin, harici modüllerde veya diğer projelerde kullanılması için include anahtar kelimesinden yararlanılır.

Aslında OOP’e ihtiyaç duyulmayan noktalarda Module kullanılmasının önerildiğine şahit oluruz. Yani belirli operasyonları gerçekleştirmek için sınıfa/sınıflara gerek olmayabilir. Sadece fonksiyonelliklerin olması yeterlidir. Bu gibi durumlarda ilgili fonksiyonellikleri içeren modüller tercih edilebilirler. Örneğin şifreleme işlerini ele alacak ve projenin genelinde kullanılacak bir kaç fonksiyonelliğe gereksinim varsa, bunun için sınıf yazılmasına gerek olmayabilir. Sadece bir Module ve içerisine konulacak bir kaç metod çoğunlukla yeterli olacaktır. Aslına bakılırsa bu operasyonların modüle olmaksızın global fonksiyon olarak tanımlanması da mümkündür. Ne var ki böyle bir oluşum sonrası aynı isimli fonksiyonların çakışması ihtimali de vardır. Ayrıca şifreleme ile ilgili operasyonların buna uygun bir isim alanı altında toplanması modülerlik açısından önemlidir.

Dilerseniz basit bir örnek ile Module kullanımını incelemeye çalışalım. Örnekte iki farklı Ruby dosyası kullanılmaktadır. UsingModules.rb isimli dosya içerisinde, Serializer.rb dosyasında yer alan Serializer modülü' de referans edilmiş ve ele alınmıştır. Kod içerikleri aşağıdaki gibidir.

Serializer.rb içeriği

module Serializer
	def self.serialize(data)
		puts "#{data} serilestiriliyor"
	end

	def self.deserialize(data)
		puts "#{data} ters serilestiriliyor"
	end
end

 UsingModules.rb içeriği

$LOAD_PATH << '.'
require "Serializer"
module Grid
	DEFAULT_PROVIDER="MONGODB"
	DEFAULT_TIMEOUT=1000
	include Serializer
	
	def self.configure
		puts "ortam #{DEFAULT_PROVIDER} icin set edildi"
	end

	class Connection
		def self.connect(conStr)
			puts "#{conStr} icin baglanti saglaniyor"
		end
		
		def self.disconnect(conStr)
			puts "#{conStr} baglantisi kesiliyor"
		end
	end

	module Cloud
		def self.connectToService(url)
			puts "#{url} adresine baglanti gerceklestirilecek"
		end

		def self.send(someData)
			puts Serializer::serialize(someData)
			puts Serializer::deserialize(someData)
		end
	end
end

if __FILE__==$0
	puts Grid::DEFAULT_PROVIDER
	Grid::configure
	Grid::Cloud::connectToService("http://somedomain/someService.svc")
	Grid::Cloud::send("Bir veri")
	Grid::Connection.connect("myMongoDb connection")
	Grid::Connection.disconnect("myMongoDb connection")
end
Module adları mutlak suretle büyük harf ile başlamalıdır. Aksi takdirde çalışma zamanı "class/module name must be CONSTANT" hatası üretir.

Gelelim kod parçacığımız ile ilişkili notlarımıza.

  • Module içerisinde tanımlanan fonksiyonlarda self anahtar kelimesinin kullanıldığına dikkat edilmelidir. Module seviyesindeki bu operasyonlar, sınıf metodu olarak ele alınırlar. 
  • Module içerisinde tanımlanan Constant' lara (DEFAULT_PROVIDER ve DEFAULT_TIMEOUT gibi) ve sınıf metodlarına MODULE_ADI::UYEADI notasyonu ile erişilir. 
  • Bir Module içerisinde metod ve sabit tanımlamaları yapılabileceği gibi sınıf ve iç module bildirimleri de yer alabilir. Örnekte yer alan Grid modülü içerisinde Connection isimli bir sınıf ve Cloud isimli bir Module tanımı yer almaktadır. Bu alt modül veya sınıflara erişmek için yine MODULE_ADI::SINIF_ADI/MODULE_ADI notasyonundan yararlanılır.
  • Farklı bir dosyada konuşlandırılan Module' leri bir sınıf içerisinde ya da başka bir modülün tamamında kullanmak için include MODULE_ADI ifadesinden yararlanılır. UsingModules.rb kodunun ilk iki satırında ilgili modülün yer aldığı dosyanın aynı klasörde aranması gerektiği $LOAD_PATH ile belirtilmiştir. Bir sonraki satırda yer alan require ifadesi ile de Serializer dosyası işaret edilmiştir.
require kullanımı C,C++ taki include ve Java' daki import kullanımına benzetilebilir.

Böylece geldik bir kod parçacığımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim. Tabii eğer böyle bir şey mümkünse.

Yorum ekle

Loading