Birleşmiş Milletler Sürdürülebilir 2030 Kalkınma Hedefleri (SKH)



  1. Yoksulluğu tüm biçimleriyle her yerde sonlandırın.
  2. Açlığı sonlandırın, gıda güvenliğini ve gelişmiş beslenmeyi sağlayın ve sürdürülebilir tarımı teşvik edin.
  3. Sağlıklı yaşamlar sağlayın ve her yaştan herkes için refahı teşvik edin.
  4. Kapsayıcı ve eşitlikçi kaliteli eğitim sağlayın ve herkes için yaşam boyu öğrenme fırsatlarını teşvik edin.
  5. Cinsiyet eşitliğini sağlayın ve tüm kadınları ve kızları güçlendirin.
  6. Herkes için su ve sanitasyonun mevcudiyetini ve sürdürülebilir yönetimini sağlayın.
  7. Herkes için uygun fiyatlı, güvenilir, sürdürülebilir ve modern enerjiye erişim sağlayın.
  8. Herkes için sürdürülebilir, kapsayıcı ve sürdürülebilir ekonomik büyümeyi, tam ve üretken istihdamı ve insana yakışır işi teşvik edin.
  9. Dayanıklı altyapı oluşturun, kapsayıcı ve sürdürülebilir sanayileşmeyi teşvik edin ve yeniliği teşvik edin.
  10. Ülkeler içinde ve arasında eşitsizliği azaltın.
  11. Şehirleri ve insan yerleşimlerini kapsayıcı, güvenli, dayanıklı ve sürdürülebilir hale getirin.
  12. Sürdürülebilir tüketim ve üretim kalıpları sağlayın.
  13. İklim değişikliği ve etkileriyle mücadele etmek için acilen harekete geçin.
  14. Sürdürülebilir kalkınma için okyanusları, denizleri ve deniz kaynaklarını koruyun ve sürdürülebilir şekilde kullanın.
  15. Karasal ekosistemlerin sürdürülebilir kullanımını koruyun, restore edin ve teşvik edin, ormanları sürdürülebilir bir şekilde yönetin, çölleşmeyle mücadele edin ve arazi bozulmasını durdurun ve tersine çevirin ve biyolojik çeşitlilik kaybını durdurun.
  16. Sürdürülebilir kalkınma için barışçıl ve kapsayıcı toplumları teşvik edin, herkes için adalete erişim sağlayın ve her düzeyde etkili, hesap verebilir ve kapsayıcı kurumlar inşa edin.
  17. Sürdürülebilir kalkınma için uygulama araçlarını güçlendirin ve küresel ortaklığı canlandırın.


SOLID Prensipleri -The Liskov Substitution Principle - Uncle Bob Çevirisi

Merhaba, bu seride sizlere Uncele Bob'un (Robert C. Martin) SOILD presnipleri için yazdığı makaleleri Türkçe'ye çevireceğim. Umarım yararlı bir yazı dizisi olur.

Seri'nin diğer yazıları :

The Single Responsibility Principle

Open Closed Principle

3- The Liskov Substitution Principle

GİRİŞ

Bu ilke, sürdürülebilir ve tekrar kullanılabilir kod oluşturma temelidir. İyi tasarlanmış kodun değiştirilmeden genişletilebileceğini belirtir; iyi tasarlanmış bir programda eski, halihazırda çalışan kodu değiştirmek yerine yeni kod eklenerek yeni özellikler eklenmesini amaç edinir.

Açık-Kapalı prensibinin ardındaki birincil mekanizmalar soyutlama ve polimorfizmdir. C ++ gibi statik olarak yazılmış dillerde, soyutlama ve polimorfizmi destekleyen temel mekanizmalardan biri kalıtımdır. Soyut temel sınıflarda saf sanal fonksiyonlar tarafından tanımlanan soyut polimorfik arayüzlere uyan türetilmiş sınıflar oluşturabiliriz.

Bu özel miras kullanımını yöneten tasarım kuralları nelerdir? En iyi miras hiyerarşilerinin özellikleri nelerdir? Açık-Kapalı prensibine uymayan hiyerarşiler yaratmamıza neden olacak tuzaklar nelerdir? Bunlar bu makalenin ele alacağı sorular olacak.

PRENSİP

POINTERLARI VEYA TEMEL SINIFLARIN REFERANSLARINI  KULLANAN FONKSİYONLAR, TÜREDİKLERİ SINIFLARIN NESNELERİNİ TİPLERİNİ BİLMEDEN KULLANABİLMELİDİRLER.

Yukarıdaki, Liskov İkame Prensibi'nin (LSP) bir açıklamasıdır. Barbara Liskov ilk olarak yaklaşık 8 yıl önce şunu yazmıştır:

Burada istenen şu ikame özelliğine benzer bir şeydir: S tipindeki her bir o1 nesnesi için T tipinde bir O2 nesnesi varsa, T olarak tanımlanan tüm P programları için, o1 o2 yerine ikame edildiğinde P'nin davranışı değişmiyorsa, o zaman S, T'nin bir alt tipidir.

Bu ilkenin önemi, ihlal etmenin sonuçlarını düşündüğünüzde belirginleşir. LSP'ye uymayan bir metod varsa, bu metod bir temel sınıfa bir işaretçi veya başvuru kullanır, ancak bu temel sınıfın tüm alt sınıflarını bilmelidir. Böyle bir işlev Açık-Kapalı ilkesini ihlal eder, çünkü temel sınıfın yeni bir alt sınıfı oluşturulduğunda değiştirilmesi gerekir.

LSP İhlaline Basit Bir Örnek

Bu ilkenin en göze çarpan ihlallerinden biri, bir nesnenin tipine dayalı bir metod seçmek için C ++ Çalışma Zamanı Türü Bilgilerinin (RTTI) kullanılmasıdır. yani .:

void DrawShape(const Shape& s)
{
if (typeid(s) == typeid(Square))
  DrawSquare(static_cast < square > (s)); 
else if (typeid(s) == typeid(Circle))
  DrawCircle(static_cast < circle > (s));
}

[Not: static_cast yeni cast operatörlerinden biridir. Bu örnekte normal bir cast gibi çalışır. yani DrawSquare ((Square &) s); Bununla birlikte, yeni sözdiziminin kullanımı daha güvenli ve grep gibi araçlarla bulunması daha katı kurallara sahiptir. Bu nedenle tercih edilir.]

Açıkçası DrawShape metodu kötü bir şekilde oluşturulmuştur. Shape sınıfının her olası alt sınıfı bilmeli ve yeni Shape alt sınıfları her oluşturulduğunda değiştirilmelidir. Gerçekten de birçoğu bu metodun yapısını Nesneye Dayalı Tasarıma lanetli olarak görmektedir.

Kare ve Dikdörtgen, Daha İnce Bir İhlal.

Ancak, LSP'yi ihlal etmenin çok daha incelikli başka yolları da vardır. Aşağıda açıklandığı gibi Rectangle sınıfını kullanan bir uygulama düşünün:



class Rectangle
{
	public:
		void SetWidth(double w) {itsWidth=w;}
		void SetHeight(double h) {itsHeight=w;}
		double GetHeight() const {return itsHeight;}
		double GetWidth() const {return itsWidth;}
	private:
		double itsWidth;
		double itsHeight;
};

Bu uygulamanın iyi çalıştığını ve birçok sitede kurulu olduğunu hayal edin. Tüm başarılı yazılımlarda olduğu gibi, kullanıcılarının ihtiyaçları değiştikçe yeni fonksiyonlara ihtiyaç duyulmaktadır. Bir gün kullanıcıların dikdörtgenlere ek olarak kareleri de işleme yeteneği talep ettiğini hayal edin.

C++'da kalıtımın ISA ilişkisi olduğu sıklıkla söylenir. Başka bir deyişle, yeni bir tür nesnenin eski tür bir nesneyle ISA ilişkisini yerine getirdiği söylenebilirse, o zaman yeni nesnenin sınıfı eski nesnenin sınıfından türetilmelidir.

Açıkça, bir kare, tüm normal niyet ve amaçlar için bir dikdörtgendir. ISA ilişkisi geçerli olduğundan, Square sınıfını Rectangle'dan türetilmiş olarak modellemek mantıklıdır.


ISA ilişkisinin bu kullanımı birçok kişi tarafından Nesne Yönelimli Analizin temel tekniklerinden biri olarak kabul edilir. Bir kare bir dikdörtgendir ve bu nedenle Square sınıfı, Rectangle sınıfından türetilmelidir. Bununla birlikte, bu tür bir düşünce, bazı ince, ancak önemli sorunlara yol açabilir. Genellikle bu sorun, biz uygulamayı gerçekten kodlamaya çalışana kadar öngörülemez. İlk ipucumuz, bir Square'in hem ItsHeight hem de itsWidth üye değişkenlerine ihtiyaç duymadığı gerçeği olabilir. Yine de onları yine de miras alacak. Açıkçası bu israf. Ayrıca, yüz binlerce Square nesnesi oluşturacaksak (örneğin, karmaşık bir devrenin her bileşeninin her pininin bir kare olarak çizildiği bir CAD/CAE programı), bu israf son derece önemli olabilir.

Ancak, bellek verimliliğiyle pek ilgilenmediğimizi varsayalım. Başka sorunlar var mı? Aslında! Square, SetWidth ve SetHeight işlevlerini devralır. Bir karenin genişliği ve yüksekliği aynı olduğundan, bu işlevler bir Kare için kesinlikle uygun değildir. Bu, tasarımda bir sorun olduğuna dair önemli bir ipucu olmalıdır. Ancak, sorunu ortadan kaldırmanın bir yolu var. Set-Width ve SetHeight'ı aşağıdaki gibi geçersiz kılabiliriz:

void Square::SetWidth(double w)
{
	Rectangle::SetWidth(w);
	Rectangle::SetHeight(w);
}
void Square::SetHeight(double h)
{
	Rectangle::SetHeight(h);
	Rectangle::SetWidth(h);
}
Şimdi, birisi bir Square nesnesinin genişliğini ayarladığında, yüksekliği de buna bağlı olarak değişecektir. Ve birisi yüksekliğini ayarladığında genişlik de onunla birlikte değişecektir. Böylece, Karenin değişmezleri bozulmadan kalır. Square nesnesi matematiksel olarak uygun bir kare olarak kalacaktır.
 
  Square s;
s.SetWidth(1); // Fortunately sets the height to 1 too.
s,SetHeight(2); // sets width and heigt to 2, good thing.

Ama aşağıdaki fonksiyonu bir düşünün

void f(Rectangle r)
{
r.SetWidth(32); // calls Rectangle::SetWidth
}

Bu fonksiyona bir Square nesnesine bir referans iletirsek, yükseklik değişmeyeceği için Square nesnesi bozulacaktır. Bu, LSP'nin açık bir ihlalidir. f işlevi, bağımsız değişkenlerinin türevleri için çalışmaz. Başarısızlığın nedeni, SetWidth ve SetHeight'ın Rectangle'da virtual olarak bildirilmemesidir.

Bunu kolayca düzeltebiliriz. Ancak, türetilmiş bir sınıfın oluşturulması, temel sınıfta değişiklik yapmamıza neden olduğunda, genellikle tasarımın hatalı olduğu anlamına gelir. Gerçekten de Açık-Kapalı ilkesini ihlal ediyor. Buna, SetWidth ve SetHeight'ı sanal yapmayı unutmanın gerçek tasarım hatası olduğu ve şu anda onu düzelttiğimiz iddiasıyla karşı çıkabiliriz. Ancak, bir dikdörtgenin yüksekliğini ve genişliğini ayarlamak son derece ilkel işlemler olduğundan, bunu haklı çıkarmak zordur. Square'in varlığını tahmin etmeseydik, hangi akıl yürütmeyle onları sanal hale getirirdik.

Yine de, argümanı kabul ettiğimizi ve sınıfları düzelttiğimizi varsayalım. Aşağıdaki kodla tamamlıyoruz:
 
   class Rectangle
	{
	public:
		virtual void SetWidth(double w) {itsWidth=w;}
		virtual void SetHeight(double h) {itsHeight=h;}
		double GetHeight() const {return itsHeight;}
		double GetWidth() const {return itsWidth;}
    private:
		double itsHeight;
	double itsWidth;
	};
	class Square : public Rectangle
	{
	public:
		virtual void SetWidth(double w);
		virtual void SetHeight(double h);
	};
	void Square::SetWidth(double w)
	{
		Rectangle::SetWidth(w);
		Rectangle::SetHeight(w);
	}
	void Square::SetHeight(double h)
	{
		Rectangle::SetHeight(h);
		Rectangle::SetWidth(h);
	}
   
   
Gerçek Sorun

Bu noktada, işe yarıyor gibi görünen Kare ve Dikdörtgen olmak üzere iki sınıfımız var. Bir Square nesnesine ne yaparsanız yapın, matematiksel bir kare ile tutarlı kalacaktır. Ve bir Rectangle nesnesine ne yaparsanız yapın, o matematiksel bir dikdörtgen olarak kalacaktır. Ayrıca, bir Dikdörtgen'e bir işaretçi veya referans kabul eden bir fonksiyona bir Kare iletebilirsiniz ve Kare yine bir kare gibi davranacak ve tutarlı kalacaktır.

Böylece, modelin artık kendi içinde tutarlı ve doğru olduğu sonucuna varabiliriz. Ancak bu sonuç yanlış olacaktır. Kendinden tutarlı bir model, tüm kullanıcıları ile mutlaka tutarlı olmak zorunda değildir! Aşağıdaki g fonksiyonunu düşünün.

void g(Rectangle& r)
{
	r.SetWidth(5);
	r.SetHeight(4);
	assert(r.GetWidth() * r.GetHeight()) == 20);
}

Bu işlev, bir Dikdörtgen olduğuna inandığı şeyin SetWidth ve SetHeight üyelerini çağırır. İşlev, bir Dikdörtgen için gayet iyi çalışır, ancak bir Kare iletilirse bir onaylama hatası bildirir. İşte asıl sorun şu: Bu işlevi yazan programcı, bir Dikdörtgenin genişliğini değiştirmenin yüksekliğini değiştirmediğini varsaymakta haklı mıydı?


Açıkçası, g programcısı bu çok makul varsayımı yaptı. Programcıları bu varsayımı yapan fonksiyonlara bir Kare iletmek problemlere yol açacaktır. Bu nedenle, Rectangle nesnelerine işaretçiler veya referanslar alan, ancak Square nesneleri üzerinde düzgün çalışamayan işlevler vardır. Bu işlevler, LSP'nin ihlal edildiğini ortaya çıkarır. Dikdörtgen'in Kare türevinin eklenmesi bu işlevi bozmuştur; ve böylece Açık-Kapalı ilkesi ihlal edilmiştir.


Geçerlilik İçsel Değildir

Bu bizi çok önemli bir sonuca götürüyor. Tek başına bakıldığında bir model anlamlı bir şekilde doğrulanamaz. Bir modelin geçerliliği ancak müşterileri açısından ifade edilebilir. Örneğin Square ve Rectangle sınıflarının son halini ayrı ayrı incelediğimizde kendi içinde tutarlı ve geçerli olduklarını gördük. Ancak onlara temel sınıf hakkında makul varsayımlarda bulunan bir programcının bakış açısından baktığımızda model bozuldu.

Bu nedenle, belirli bir tasarımın uygun olup olmadığı değerlendirilirken, çözüme tek başına bakmamak gerekir. Bu tasarımın kullanıcıları tarafından yapılacak makul varsayımlar açısından değerlendirilmelidir.

Ne yanlış gitti?

Peki ne oldu? Görünüşe göre makul olan Kare ve Dikdörtgen modeli neden kötü gitti? Sonuçta, Kare Dikdörtgen değil mi? ISA ilişkisi devam etmiyor mu?

Hayır! Bir kare bir dikdörtgen olabilir, ancak bir Square nesnesi kesinlikle bir Rectangle nesnesi değildir. Niye? Çünkü bir Square nesnesinin davranışı, bir Rectangle nesnesinin davranışıyla tutarlı değildir. Davranışsal olarak, Kare Dikdörtgen değildir! Ve yazılımın gerçekten ilgili olduğu şey davranıştır.

LSP, OOD'de ISA ilişkisinin davranışla ilgili olduğunu açıkça ortaya koymaktadır. İçsel özel davranış değil, dışsal kamusal davranış; clientlerın bağlı olduğu davranış. Örneğin, yukarıdaki g fonksiyonunun yazarı, Dikdörtgenlerin yükseklikleri ve genişlikleri birbirinden bağımsız olarak değişecek şekilde davranmasına bağlıydı. İki değişkenin bu bağımsızlığı, diğer programcıların muhtemelen bağımlı olduğu dışsal bir genel davranıştır.

LSP'nin ve onunla birlikte Açık-Kapalı ilkesini tutması için, tüm türevlerin, müşterilerin kullandıkları temel sınıflardan beklediği davranışa uyması gerekir.

Sözleşmeye Göre Tasarım (Design By Contract)


LSP ile Bertrand Meyer2 tarafından açıklandığı üzere Sözleşmeye Göre Tasarım kavramı arasında güçlü bir ilişki vardır. Bu şemayı kullanarak, sınıf metotları önkoşulları ve sonkoşulları bildirir. Yöntemin uygulanabilmesi için ön koşulların doğru olması gerekir. Tamamlandığında, yöntem, son koşulun doğru olacağını garanti eder.

Rectangle::SetWidth(double w) öğesinin son durumunu şu şekilde görebiliriz:

assert((itsWidth == w) && (itsHeight == old.itsHeight)); Şimdi, Meyer3 tarafından belirtildiği gibi, türevler için ön koşullar ve son koşullar için kural şudur:

...bir rutini [türevde] yeniden tanımlarken, yalnızca ön koşulunu daha zayıf olanla ve son koşulunu daha güçlü olanla değiştirebilirsiniz.

Başka bir deyişle, bir nesneyi temel sınıf arabirimi aracılığıyla kullanırken, kullanıcı yalnızca temel sınıfın ön koşullarını ve son koşullarını bilir. Bu nedenle, türetilmiş nesneler, bu tür kullanıcıların, temel sınıfın gerektirdiğinden daha güçlü olan ön koşullara uymasını beklememelidir. Yani, temel sınıfın kabul edebileceği her şeyi kabul etmeleri gerekir. Ayrıca, türetilmiş sınıflar, tabanın tüm son koşullarına uygun olmalıdır. Yani, davranışları ve çıktıları, temel sınıf için belirlenen kısıtlamaların hiçbirini ihlal etmemelidir. Temel sınıfın kullanıcıları, türetilmiş sınıfın çıktısıyla karıştırılmamalıdır.

Açıkça, Square::SetWidth(double w) öğesinin son koşulu, “(itsHeight == old.itsHeight)” temel sınıf yan tümcesine uymadığından, yukarıdaki Rectangle::SetWidth(double w) öğesinin son koşulundan daha zayıftır. Bu nedenle, Square::SetWidth(double w) temel sınıfın sözleşmesini ihlal eder.

Eiffel gibi bazı diller, ön koşullar ve son koşullar için doğrudan desteğe sahiptir. Bunları gerçekten bildirebilir ve çalışma zamanı sisteminin bunları sizin için doğrulamasını sağlayabilirsiniz. C++'ın böyle bir özelliği yoktur. Yine de C++'da bile her yöntemin ön koşullarını ve son koşullarını manuel olarak değerlendirebilir ve Meyer kuralının ihlal edilmediğinden emin olabiliriz. Ayrıca, bu ön koşulları ve son koşulları her bir yöntem için yorumlarda belgelemek çok yardımcı olabilir.

A real Example Kısmını çevirmedim. Orjinal makaleden gözatabilirsiniz.


ÖZET SONUÇ

Açık-Kapalı prensibi, OOD için yapılan iddiaların çoğunun kalbinde yer alır. Bu ilke yürürlükte olduğunda, uygulamalar daha sürdürülebilir, tekrar kullanılabilir ve sağlamdır. Liskov İkame İlkesi (Diğer adıyla Sözleşmeli Tasarım (Design by Contract)), Açık-Kapalı prensibine uyan tüm programların önemli bir özelliğidir. Sadece alt sınıflar temel tipleri için tamamen ikame edildiğinde, bu temel sınıfları kullanan metodlar cezasızlıkla yeniden kullanılabilir ve alt tipler cezasızlıkla değiştirilebilir.

Metnin Orjinali :


Learn English with Alex

Bundan 2 ay öncesi kadar İngilizce özel ders almaya karar vermiştim.
Sonra Alex ile tanıştım. 2 ay boyunca 40 akademik saat ders yaptık.
Kendisi az Türkçe biliyor. Hemen hemen hiç Türkçe konuşmadık.
Her konuda konuştuk, bolca pratik yaptık. Her ders öncesi Extra English sitcom dizisinden bir bölüm izleyip kendisine reported speech yaptım. Ayrıca bir ödevim de McMillian'ın Destination B1 Grammar & Vocabulary kitabından bir ünite bitirmekti. Bir dönem IELTS Academic sınavına da hazırladı beni, fakat çok vakit bulamadığımdan bunu ileri bir tarihe erteledik.
Genel olarak İngilizcem farkedilir derecede iyileşti. Konuşurken özgüvenim arttı ve iyi bir arkadaş edinmiş oldum.
Kendisi anne tarafından İngiliz, baba tarafından Rus ve eşi Türk. Hindistan'da eğitim görmüş. Yani birçok kültürden sizinle sohbet etmek için tecrübesi var.
Siz de kendisinden ders almak isterseniz, bu grup dersi de olabilir, kendisine aşağıdaki numaradan ulaşabilirsiniz.

530 238 71 17



Açık Kaynak Tanımı ile Özgür Yazılım Tanımı Karşılaştırma

Açık Kaynak Tanımı ile Karşılaştırma





Özgür yazılım hareketi ve açık kaynaklı yazılım hareketi arasındaki felsefi farklılıklara rağmen, FSF tarafından ücretsiz yazılım ve OSI tarafından açık kaynaklı yazılımın resmi tanımları, birkaç küçük istisna dışında, temelde aynı yazılım lisanslarına atıfta bulunur. . Özgür Yazılım Vakfı, felsefi farklılıkları vurgularken şu yorumu yapıyor:


"Açık kaynaklı" yazılım terimi, bazı kişiler tarafından özgür yazılımla aşağı yukarı aynı kategoriyi ifade etmek için kullanılır. Tam olarak aynı yazılım sınıfı değildir: çok kısıtlayıcı olduğunu düşündüğümüz bazı lisansları kabul ederler ve kabul etmedikleri özgür yazılım lisansları vardır. Ancak, kategorinin genişletilmesindeki farklılıklar küçüktür: neredeyse tüm özgür yazılımlar açık kaynaklıdır ve neredeyse tüm açık kaynaklı yazılımlar özgürdür.


— Özgür Yazılım Vakfı

Özgür Yazılımın Dört Temel Özgürlüğü - wikipedia.org ÇEVİRSİ

 Özgür Yazılımın Dört Temel Özgürlüğü








FSF tarafından Şubat 1986'da yayınlanan tanımda iki nokta vardı:


Adımızdaki "FREE" kelimesi fiyat anlamına gelmez; özgürlüğe atıfta bulunur. Birincisi, bir programı kopyalama ve komşularınıza yeniden dağıtma özgürlüğü, böylece onlar da sizin kadar iyi kullanabilirler. İkincisi, programın sizi kontrol etmesi yerine sizin kontrol edebilmeniz için bir programı değiştirme özgürlüğü; bunun için kaynak kodun size sunulması gerekir.


1996'da, gnu.org web sitesi başlatıldığında, "özgür yazılım", yazılımı inceleme özgürlüğünden (iki noktalı tanımda şu şekilde okunabilir) açık bir söz eklenerek "üç özgürlük düzeyine" atıfta bulunularak tanımlandı. Stallman daha sonra "seviye" kelimesinden kaçınarak tüm özgürlüklerin gerekli olduğunu, dolayısıyla seviyeler açısından düşünmenin yanıltıcı olduğunu söyledi.


Son olarak, kullanıcıların programı çalıştırabilmesi gerektiğini açıkça söylemek için başka bir özgürlük eklendi. Mevcut özgürlükler zaten birden üçe numaralandırılmıştı, ancak bu özgürlük diğerlerinden önce gelmeliydi, bu yüzden "özgürlük sıfır" olarak eklendi.

Modern tanım, özgür yazılımı, alıcının aşağıdaki dört özgürlüğe sahip olup olmadığına göre tanımlar:


Programı istediğiniz gibi, herhangi bir amaç için çalıştırma özgürlüğü (özgürlük 0).

Programın nasıl çalıştığını inceleme ve bilgisayarınızı istediğiniz gibi yapması için değiştirme özgürlüğü (özgürlük 1). Kaynak koduna erişim bunun için bir ön koşuldur.

Komşunuza yardım edebilmeniz için kopyaları yeniden dağıtma özgürlüğü (özgürlük 2).

Değiştirilmiş sürümlerinizin kopyalarını başkalarına dağıtma özgürlüğü (özgürlük 3). Bunu yaparak, tüm topluluğa değişikliklerinizden yararlanma şansı verebilirsiniz. Kaynak koduna erişim bunun için bir ön koşuldur.


Richard Stallman tarafından yazılan ve Özgür Yazılım Vakfı (FSF) tarafından yayınlanan Özgür Yazılım Tanımı, özgür yazılımı, son kullanıcıların bu yazılımı kullanma, inceleme, paylaşma ve değiştirme özgürlüğüne sahip olmasını sağlayan yazılım olarak tanımlar. "Özgür" terimi, "ücretsiz" değil, "özgür konuşma" anlamında kullanılır. Tanımın bilinen en eski yayını, FSF tarafından artık durdurulan GNU's Bulletin yayınının Şubat 1986 baskısındaydı. Belgenin kanonik kaynağı, GNU Projesi web sitesinin felsefe bölümündedir. Nisan 2008 itibariyle burada 39 dilde yayınlanmaktadır. FSF, bu tanıma uyan lisansların bir listesini yayınlar.



Açık Kaynak Tanımı (The Open Source Definition) - opensource.org çevirisi

 Açık Kaynak Tanımı




Tanıtım

Açık kaynak sadece kaynak koduna erişim anlamına gelmez. Açık kaynaklı yazılımın dağıtım koşulları aşağıdaki kriterlere uygun olmalıdır:


1. Ücretsiz Yeniden Dağıtım

Lisans, herhangi bir tarafı, yazılımı birkaç farklı kaynaktan programları içeren toplu bir yazılım dağıtımının bir bileşeni olarak satmasını veya başka birine vermesini kısıtlamaz. Lisans, bu tür bir satış için telif hakkı veya başka bir ücret gerektirmez.


2. Kaynak Kodu

Program kaynak kodu içermeli ve kaynak kodun yanı sıra derlenmiş formda dağıtıma izin vermelidir. Bir ürünün herhangi bir biçiminin kaynak koduyla dağıtılmadığı durumlarda, kaynak kodunu makul bir çoğaltma maliyetinden fazla olmayan, tercihen İnternet üzerinden ücretsiz olarak indirerek elde etmenin iyi tanıtılmış bir yolu olmalıdır. Kaynak kodu, bir programcının programı değiştireceği tercih edilen form olmalıdır. Kasıtlı olarak karıştırılmış kaynak koduna izin verilmez. Bir önişlemcinin veya çevirmenin çıktısı gibi ara formlara izin verilmez.


3. Türetilmiş İşler

Lisans, değişikliklere ve türetilmiş çalışmalara izin vermeli ve bunların orijinal yazılımın lisansı ile aynı koşullar altında dağıtılmasına izin vermelidir.


4. Yazarın Kaynak Kodunun Bütünlüğü

Lisans, kaynak kodunun değiştirilmiş biçimde dağıtılmasını ancak lisans, "yama dosyalarının" kaynak kodla birlikte, derleme sırasında programı değiştirmek amacıyla dağıtılmasına izin veriyorsa kısıtlayabilir. Lisans, değiştirilmiş kaynak koddan oluşturulan yazılımın dağıtımına açıkça izin vermelidir. Lisans, türetilmiş çalışmaların orijinal yazılımdan farklı bir ad veya sürüm numarası taşımasını gerektirebilir.


5. Kişi ve Gruplara Karşı Ayrımcılık Yapılmaması

Lisans, herhangi bir kişi veya kişi grubuna karşı ayrımcılık yapmamalıdır.


6. Çalışma Alanlarına Karşı Ayrımcılık Yapılmaması

Lisans, hiç kimsenin programı belirli bir çalışma alanında kullanmasını kısıtlamamalıdır. Örneğin, programın bir işletmede kullanılmasını veya genetik araştırmalar için kullanılmasını kısıtlayamaz.


7. Lisansın Dağılımı

Programa bağlı haklar, bu taraflarca ek bir lisans yürütülmesine gerek kalmadan programın yeniden dağıtıldığı herkese uygulanmalıdır.


8. Lisans Bir Ürüne Özel Olmamalıdır

Programa eklenen haklar, programın belirli bir yazılım dağıtımının parçası olmasına bağlı olmamalıdır. Program bu dağıtımdan çıkarılırsa ve programın lisans koşulları dahilinde kullanılır veya dağıtılırsa, programın yeniden dağıtıldığı tüm taraflar, orijinal yazılım dağıtımıyla bağlantılı olarak verilenlerle aynı haklara sahip olmalıdır.


9. Lisans Diğer Yazılımları Kısıtlamamalıdır

Lisans, lisanslı yazılımla birlikte dağıtılan diğer yazılımlara kısıtlama getirmemelidir. Örneğin, lisans aynı ortamda dağıtılan diğer tüm programların açık kaynaklı yazılım olması konusunda ısrar etmemelidir.


10. Lisans Teknolojiden Tarafsız Olmalıdır

Lisansın hiçbir hükmü, herhangi bir bireysel teknolojiye veya arayüz stiline dayandırılamaz.

Softtech 2021 Teknoloji Raporu

 



PDF olarak buradan indirebilirsiniz.

Siteyi buradan ziyaret edebilirsiniz.

Java Object Sınıfı ve Metodları - wikibooks.org çevirisi

 

Java Programming/API/java.lang.Object



java.lang.Object


Object sınıfı, tüm Java sınıflarının üst sınıfıdır. Bu sınıftan tüm Java sınıfları miras alınır. Bu, tüm Java sınıflarında mevcut olan metodlara sahip olmamızı mümkün kılar. Bu, durumun söz konusu olmadığı 
C ++ ile karşılaştırıldığında işleri basitleştirir.

Object sınıfı metodları ve açıklamaları

boolean equals( Object o ); :  Nesneleri karşılaştırmak için genel bir yol sağlar

Class getClass();             :  Class sınıfı bize nesne hakkında daha fazla bilgi verir

int hashCode();                  :  Bir koleksiyondaki nesneleri aramak için kullanılan bir hash değeri döndürür

void notify();                      :  synchronizing thread'lerde kullanılır

void notifyAll();                 :  synchronizing thread'lerde kullanılır

String toString();                :  Nesneyi String'e dönüştürmek için kullanılabilir

void wait();                         :  synchronizing thread'lerde kullanılır

protected Object clone() throws CloneNotSupportedException ; : Mevcut nesneyle tamamen aynı olan yeni bir nesne döndür.

protected void finalize() throws Throwable; : Bu metod garbage collection nesneyi toplamadan hemen önce çalışır.

equals() Metodu


Boolean equals (Object o) yöntemi, nesneleri eşitlik açısından karşılaştırmak için genel bir yol sağlar. Sınıfınızda onu override etmeniz gerekir. O zaman şu şekilde yazabilirsiniz:
  public boolean isCustomerExist( Customer newCustomer )
{
   boolean isRet = false;
   Iterator iter = _collAllCustomer.iterator();
   while ( iter.hasNext() )
   {
      if ( newCustomer.equals( (Customer) iter.next() )
      {
         // -- Customer was found ---
         isRet = true;
      }
   }
  return isRet;
}
  
  
equals() öğesini geçersiz kıldığınızda, her zaman hashCode() öğesini de geçersiz kılmanız gerektiğini unutmayın, böylece iki yöntem tutarlı olur. İki nesne eşitse, aynı hashcode'a sahip olmaları gerekir.

hashCode() Metodu


Çoğu durumda, bu yöntemin varsayılan uygulaması nesne için benzersiz bir sayı döndürdüğünden, bu yöntemi geçersiz kılmamalısınız. Sayı, nesne bir koleksiyona konulduğunda kullanılır. Büyük bir koleksiyonda bir nesneyi bulmak, nesneler tek tek sırayla karşılaştırılırsa biraz zaman alabilir. Aramayı hızlandırmak için, nesneler bir tamsayı karma kod ile ağırlıklandırılan bir ağaç yapısına yerleştirilebilir. Ağaçta gezinirken karma kodu karşılaştırarak, nesne karşılaştırma sayısı azaltılabilir.

   _______ A _____
   |              |  
__ B__          __C__
|     |        |     |
D     E        F     G
...  ...      ...   ...
Size nasıl çalıştığı hakkında genel bir fikir vermek için yukarıdaki şemaya bakın. G nesnesini aradığımızı varsayalım. Ağacın her bir 'düğümünde' hangi yöne gideceğimize karar verebilirsek, 3 adımda G nesnesine ulaşırız.

Doğrusal bir aramada yorumla:

A --- B  ----- C  ---- C  ---- D  ---- E ---- F ---- G
G nesnesine ulaşmak için 8 adıma ihtiyacımız var.

Böylece ağaç yapısı ile arama daha hızlı olacaktır. Ancak yeni bir nesne eklemek daha yavaş olacaktır çünkü ağaç yapısının korunması gerekir. Yeni nesnenin ağaçtaki yeri ilk önce bulunmalıdır.

getClass() Metodu

Programınızdaki her sınıf için bir Class nesnesi vardır. Her dizi, aynı öğe türüne ve boyut sayısına sahip tüm diziler tarafından paylaşılan bir Class nesnesi olarak yansıtılan bir sınıfa da aittir. İlkel Java türleri (boolean, byte, char, short, int, long, float ve double) ve void anahtar sözcüğü de Class nesneleri olarak temsil edilir. Class'ın genel kurucusu yoktur. Bunun yerine Class nesneleri, sınıflar yüklenirken Java Sanal Makinesi tarafından otomatik olarak oluşturulur.

Class'ın en popüler kullanımı, çalışma zamanı sırasında nesnenin sınıf adını bulmaktır.
  ,
  import com.yourCompany.Customer;
...
Object obj = new Customer();
...
System.out.println( "Name:" + obj.getClass().getName() );
  
 

toString() Metodu


Bu yöntem, bir nesneyi bir String'e dönüştürmek için kullanılabilir. Nesneleri String'e dönüştürmek için birçok yerde otomatik olarak kullanılır; örneğin: PrintStream'de, StringBuffer'da ve nesnelerde kullanıldığında string concatenation operatörü için.

Varsayılan uygulama, sınıf adı ve hash kodu ile garip bir dize döndürür.

Örneğin:


  
  String str = "This customer is " + objCust;
  
ToString () yöntemi objCust nesnesinde çağrılır. ToString () yöntemi, debugging için de kullanılabilir:
  
  public class Customer
{
   private String _name;
   private String _address;
   private String _age;
...
   public String toString()
   {
       StringBuffer buf = new StringBuffer();
       buf.append( "Name   = " );  buf.append( _name );     buf.append( "\n" );
       buf.append( "Address= " );  buf.append( _address );  buf.append( "\n" );
       buf.append( "Age    = " );  buf.append( _age );      buf.append( "\n" );
    ...
       return buf.toString();
   }
...
}
  
Bundan sonra, kodunuzda ne zaman bir müşteri nesnesinin ne olduğunu görmek istersiniz, sadece şunu kullanabilirsiniz:
  
  System.out.println( objCustomer );
  

Synchronizing Thread'lerin Metodları


Çok iş parçacıklı bir ortamda, birden fazla iş parçacığı bir kaynağa erişip değiştirebildiğinde, sonuç tahmin edilemez olabilir. Örneğin, birden fazla iş parçacığı tarafından artırılan bir sayaç değişkenimiz olsun.

Dikkat! Senkronizasyon belirsiz bir terimdir. Aynı kod bölümünü aynı anda yürüten tüm iş parçacıklarını yapmaktan ibaret değildir. Tam tersi. Herhangi iki iş parçacığının aynı kod bölümünü aynı anda yürütmesini engeller. Bir işlemin sonunu ikinci bir işlemin başlangıcıyla senkronize eder.





Yukarıdaki kod, aşağıdaki alt işlemlerle oluşturulmuştur:

Read; değişken sayacını oku
Add; değere 1 ekle
Save ; yeni değeri değişken sayaca kaydet
Diyelim ki iki iş parçacığının bu kodu çalıştırması gerekiyor ve eğer sayaç değişkeninin başlangıç değeri sıfır ise, işlemlerden sonra değerin 2 olmasını bekliyoruz.


Yukarıdaki durumda Thread 1 işlemi kaybolur, çünkü Thread 2 kendi değerinin üzerine yazar. Thread 2'nin, Thread 1 işlemi bitirene kadar beklemesini istiyoruz. Aşağıya bakınız:



Kritik Bölüm (Critical Section)
Yukarıdaki örnekte, sayaç+=1 kodu herhangi bir zamanda bir ve yalnızca bir iş parçacığı tarafından yürütülmelidir. Buna kritik bölüm denir. Programlama sırasında, çok iş parçacıklı bir ortamda, kritik bir bölüme ait olan tüm kod parçalarını tanımlamalı ve herhangi bir zamanda yalnızca bir iş parçacığının bu kodları çalıştırabildiğinden emin olmalıyız. Buna senkronizasyon denir.

Konuları senkronize etme (Synchronizing threads)
Kritik bir bölüm koduna iş parçacığı erişimi, iş parçacıkları arasında senkronize edilmelidir, yani herhangi bir zamanda yalnızca bir iş parçacığının onu çalıştırabilmesini sağlamak için.

Nesne monitörü (Object monitor)
Her nesnenin bir Nesne monitörü vardır. Temel olarak, bir iş parçacığı tarafından kritik bir bölüm kodunun yürütülüp yürütülmediğini gösteren bir semafordur. Kritik bir bölümün yürütülebilmesi için iş parçacığının bir Nesne izleyicisi edinmesi gerekir. Bir seferde yalnızca bir iş parçacığı o nesnenin monitörüne sahip olabilir.


Bir iş parçacığı, üç yoldan biriyle nesnenin monitörünün sahibi olur

Bu nesnenin synchronized instance method yürüterek. Senkronize edilmiş anahtar kelimeye bakın.

Nesne üzerinde senkronize olan synchronized statement gövdesini yürüterek. Senkronize edilmiş anahtar kelimeye bakın.

Class türündeki nesneler için, o sınıfın synchronized static method yürüterek.

Object Monitor senkronizasyonla ilgilenir, öyleyse neden "wait() ve notify() yöntemlerine" ihtiyacımız var?

Senkronizasyon için onlara gerçekten ihtiyacımız yok, ancak bazı durumlarda bunları kullanmak güzel. Güzel ve düşünceli bir thread onları kullanacaktır. Kritik bir bölümün yürütülmesi sırasında iş parçacığı sıkışmış olabilir, devam edemeyebilir. Bir IO ve diğer kaynakları beklediği için olabilir. Her durumda, iş parçacığının nispeten uzun bir süre beklemesi gerekebilir. İş parçacığının nesne monitörüne tutunması ve diğer iş parçacıklarının işini yapmasını engellemesi bencillik olurdu. Böylece iş parçacığı, nesne üzerinde wait() yöntemini çağırarak bir 'bekleme' durumuna gider. İş parçacığının nesne monitörünü aldığı aynı nesne olmalıdır.
Öte yandan, bir iş parçacığı, yalnızca, kaynak kullanılabilir olduğunda notify() yöntemini çağıracak en az bir başka iş parçacığı varsa, wait() yöntemini çağırmalıdır, aksi takdirde iş parçacığı, bir parametre olarak zaman aralığı belirtilir.
Bir benzetme yapalım. Bazı eşyaları almak için bir dükkana girersiniz. Tezgahta sıraya girersiniz, satış memurunun dikkatini çekersiniz - onun "nesne-monitörünü" alırsınız. İstediğiniz ürünü soruyorsunuz. Bir depodan bir ürün getirilmesi gerekiyor. Beş dakikadan fazla sürecektir, bu nedenle satış memurunu serbest bırakırsınız ("nesne monitörünü" ona geri verin), böylece diğer müşterilere hizmet verebilir. Bekleme durumuna geçersiniz. Diyelim ki bekleyen beş müşteri daha var. Depodan eşyaları getiren başka bir satış memuru var. Bunu yaparken, ilk satış memurunun dikkatini çeker, nesne monitörünü alır ve bekleyen bir veya tüm müşteriyi/müşterileri bilgilendirir, böylece bekleyen müşteri(ler) uyanır ve müşterinin dikkatini çekmek için tekrar sıraya girer. ilk satış memuru.
Bekleyen müşteri ile ürünleri getiren satış memuru arasındaki senkronizasyona dikkat edin. Bu bir tür üretici-tüketici senkronizasyonudur.
Ayrıca, ilk satış memuruna ait yalnızca bir nesne monitörü olduğunu unutmayın. Beklemeden ve bir bildirimin gerçekleşebilmesi için önce bu nesne-monitörünün/memurun notify edilmesi gerekir.

final void wait() yöntemi
Geçerli iş parçacığı, bu nesnenin monitörüne sahip olmalıdır. İş parçacığı, bu monitörün sahipliğini serbest bırakır ve başka bir iş parçacığı, bu nesnenin monitöründe bekleyen iş parçacıklarının, notify yöntemine veya notifyAll yöntemine yapılan bir çağrı yoluyla uyanmasını bildirene kadar bekler. İş parçacığı daha sonra monitörün sahipliğini yeniden elde edene ve yürütmeye devam edene kadar bekler.
final void wait (long time)
Bekleme ile aynıdır, ancak bir bildirim olup olmadığına bakılmaksızın belirtilen süre geçtikten sonra iş parçacığı uyanır.
final void notify()
Bu yöntem yalnızca bu nesnenin monitörünün sahibi olan bir iş parçacığı tarafından çağrılmalıdır. Bu nesnenin monitöründe bekleyen tek bir iş parçacığını uyandırır. Bu nesnenin monitöründe çok sayıda iş parçacığı bekliyorsa, bunlardan biri uyandırılmak üzere seçilir. Seçim keyfidir ve uygulamanın takdirine bağlı olarak gerçekleşir. Bir iş parçacığı, bekleme yöntemlerinden birini çağırarak bir nesnenin monitöründe bekler.
Uyandırılan iş parçacığı, mevcut iş parçacığı bu nesne üzerindeki kilidi bırakana kadar ilerleyemeyecektir. Uyandırılan iş parçacığı, bu nesne üzerinde eşzamanlamak için aktif olarak rekabet edebilecek diğer iş parçacıklarıyla olağan şekilde rekabet edecektir; örneğin, uyanmış iş parçacığı, bu nesneyi kilitleyecek bir sonraki iş parçacığı olma konusunda güvenilir bir ayrıcalığa veya dezavantaja sahip değildir.
final void notifyAll()
notify() ile aynıdır, ancak bu nesnenin monitöründe bekleyen tüm iş parçacıklarını uyandırır.

sleep() ve wait() yöntemleri arasındaki farklar nelerdir?
Thread.sleep(milis)
Bu, Thread sınıfının statik bir yöntemidir. Şu anda yürütülmekte olan iş parçacığının belirtilen milisaniye sayısı boyunca uyumasına (yürütmeyi geçici olarak durdurmasına) neden olur. İş parçacığı herhangi bir monitörün sahipliğini kaybetmez. Bu, iş parçacığının bir nesne izleyicisi varsa, bu monitöre ihtiyaç duyan diğer tüm iş parçacıklarının engellendiği anlamına gelir. Bu yöntem, iş parçacığının herhangi bir monitörü olup olmadığına bakılmaksızın çağrılabilir.
wait()
Bu yöntem, Object sınıfından miras alınır. İş parçacığı, wait() yöntemini çağırmadan önce o nesnenin nesne monitörünü almış olmalıdır. Nesne izleyicisi wait() yöntemiyle serbest bırakılır, bu nedenle bu nesne izleyicisini isteyen diğer bekleyen iş parçacıklarını engellemez.



Rastgele İçerik

DonanımHaber

© tüm hakları saklıdır
made with by templateszoo