Çevirmenimizi Kullanırken Java Kodunun Kalitesi Nasıl Artırılır

C#'daki yaklaşımları ve dil yapılarını tartışacağız: hangilerinin kullanılması iyi, hangilerinin iyi olmadığı. Elbette, iyi veya kötü olarak aşağıdakileri düşünüyoruz: C#'den çeviri sonucu elde edilen Java kodunun okunabilir ve bakımı kolay olacak mı?

C#'da Kompakt – Java'da Büyük

C#, birçok gizli iş yapabilen kompakt dil yapılarına sahiptir. Bu yapıları başka bir dile çevirirken, bu gizli kısmı zımnen yeniden üretmek zorundasınız ve çoğu durumda kod orijinal tasarımını kaybeder ve çok farklı hale gelir.

Otomatik özellikler (Auto-properties)

Otomatik özellikler, C# programcıları arasında yaygın olarak kullanılır. Bu tür bir özellikle programcı, gizli alanla get ve/veya set yöntemi aracılığıyla etkileşimde bulunabilir. C#, otomatik özelliklerin gerçek uygulamasından dikkatimizi dağıtmasına izin verir ve bunları bildirmek için çok kompakt yapılar kullanır. Ancak Java'da böyle bir dil yapımız yoktur ve özellikleri açıkça bildirmek gereklidir: alan ve erişim kontrol yöntemleri olarak:

public int Value { get; set; }

Java'da ise:

private int auto_Value;
public int get_Value()
{
    return auto_Value;
}
public void set_Value(int value)
{
    auto_Value = value;
}

Artık tek bir katı üye değil, üç ayrı üye var. Her otomatik özellik için aynı kodun tekrarlandığını hayal edin, nasıl görünecekti? Böyle hoş olmayan deneyimleri önleyelim. Peki nasıl?
Otomatik özelliği, gizli alan üzerinde erişim kontrolü sağlayan bir nesneyle değiştirmeyi deneyin. Böyle nesnelerin bir hash haritası olabilir. Veriye sınırlı erişim tasarımını takip ediyorsak, bu iyi bir yol olabilir. Otomatik özellikler hoş görünebilir, ancak gereksiz yere kullanmak zorunda değiliz.

Değer Türleri

C# dilinde, yapılar için (değer türleri) ayrılmış bir bellek mantığına sahibiz. Bunların ömrü, yığın çerçevesinin veya içeren nesnenin ömrüyle sınırlıdır ve sık sık kopyalanırlar –- işlev argümanları olarak geçerken, bir işlevden dönerken veya bir alana atarken değerle, referansla değil çalışırız. Kopyayı değiştirdiğimizde, orijinali değiştirmez. Değer türlerini Java'ya çevirirken, Java sınıfları her zaman referans türleridir olmasına rağmen, aynı mantığı yeniden oluşturmamız gerekiyor. Sık sık kopyalama şimdi bir sorun haline geliyor – her kopyayı saklamak için bellek tahsis ediyoruz ve çöp toplayıcıyı aşırı yüklüyoruz. Performansı ilgi alanlarımızdan biri olarak düşünüyorsak, C# kodumuzu bellek yönetimi ayrıntılarından soyutlamamız gerekiyor. Peki ama nasıl?
Bunu yapmanın en kolay yolu –- değer türlerinizi değişmez hale getirmektir. Değişken durumunuz yoksa, bu durumu kopyalamak zorunda değilsiniz ve belirsiz davranışı önlemiş olursunuz.

Yalnızca Sözdizimi Yapıları

Şimdi, yalnızca kodun görsel özelliklerini değiştiren dil yapıları hakkında konuşma zamanı. Örneğin:

public class Item
{
    string name;
    string price;
    
    public Item(string name, int price) => (this.name, this.price) = (name, price);
    
    public string ToString() => $"Name = {name}, Price = {price}";
    public string Name => name;
    public int Price => price;
}

Burada demet çözümlemesini (bu ifade gerçekte bir demet oluşturmaz), araya girmiş dize harfli ifadeyi, ifade tabanlı yöntemleri ve özellikleri görüyoruz.

Delegeler

Delegeler, yöntem bildiriminin kısa bir formudur ve kullanmak için iyidir. Bir örneğe bakalım:

using System;
using System.Linq;

class Program
{
    delegate int ChangeNumber(int arg);
	static void Main()
	{
	    Console.WriteLine("Input some numbers");
        int[] numbers = Console.ReadLine().Split(" ").Select(int.Parse).ToArray();
        Console.WriteLine("Input addition");
        int addition = int.Parse(Console.ReadLine());
        ChangeNumbers(n => n + addition, numbers);
        Console.WriteLine("Result :");
        Console.WriteLine(string.Join(" ", numbers.Select(n => n.ToString())));
	}
	static void ChangeNumbers(ChangeNumber change, int[] numbers)
	{
	    for(int i = 0; i < numbers.Length; i++)
	    {
	        numbers[i] = change(numbers[i]);
	    }
	}
}

n => n + addition ifadesi için Java anonim sınıf ifadesi üretebiliriz:

// translated to Java code
interface ChangeNumber
{
    int invoke(int arg);
}
// ...static void main(String[] args)...

// anonymous class expression for Java 7 or older version
changeNumbers(new ChangeNumber()
{
    public int invoke(int n)
    {
        return n + addition;
    }
}, numbers);

// or lambda expression for higher Java 8 or newer version
changeNumbers(n -> n + addition, numbers);

Sonuca Varırken

C#, kodumuzu basit gösteren ve sözdizimi şekeri arkasında büyük bir uygulamayı gizleyebilecek birçok dil yapısına sahiptir. Bu yapıların bazıları sorgulanabilir ve zor desteklenebilirken, diğerleri esnek ve kolay yeniden üretilebilir. Tasarım söz konusu olduğunda, C# özel dil yapıları yerine nesnelerle soyutlamaları oluşturmak daha iyidir. Performans söz konusu olduğunda, bellek yönetiminden soyutlamayı sürdürmeli ve kendimizi iki kat maliyetle taklit etmekten kurtarmalıyız.

İlgili makaleler