İlkay İlknur

just a developer...

Portable Class Library mi ? Universal App Shared Projects mi ?

Microsoft'un son zamanlarda cross-platform uygulama ve kütüphane geliştirme tarafına yaptığı yatırım oldukça fazla. Gerek Xamarin desteğiyle beraber IOS ve Android tarafında olsun gerekse Windows Store ve Windows Phone tarafında yarattığı teknolojilerle olsun tek bir kod yazarak bu kodun farklı platformlarda çalışan uygulamalar arasında paylaştırılması şu anda bir şekilde sağlanmakta. Aslında bakarsanız bu yöntemlerin hiçbiri tam anlamda süper çözümler olmasa da gerektiği noktalarda doğru şekilde kullanıldığında kod paylaşımı konusunda çektiğimiz acıları oldukça azaltmakta. Peki hangisini ne zaman kullanmalıyız ?

Portable Class Libraries

Portable class libraryler aslında uzun zamandır hayatımızda bulunan ve farklı platformlar üzerinde çalışacak kod yazmak istediğimizde kullandığımız yapılardan ilk akla geleni.

PortableSelect

Portable class librarylerin kısıtlarında bir tanesi de içerisinde platform spesifik kod yazmanın mümkün olmaması. Bu yüzden de portable class librarylerde sadece seçtiğiniz platformlar içerisinde ortak olarak kullanılan kütüphanelere erişiminiz var.

 PortableIntersection

Yukarıda gördüğünüz gibi hangi platformları hedef olarak seçerseniz o platformların kesişiminde bulunan kütüphaneleri kullanabiliyorsunuz.

Eğer kütüphaneniz içerisinde platforma özel bir kod çalıştırmak isterseniz o kodun dışarıdan sizin kodunuz içerisine verilmesini sağlamak zorundasınız. Yani dependency injection vb.. yapıları kullanmak zorundasınız. Örneğin, bir ekran açarak dosya seçme işlemi yaptırmak isterseniz şu şekilde bir çözüm geliştirmeniz gerek.

public class MyLibrary
{
    public async Task Foo(IFileProvider provider)
    {
        var file = await provider.SelectFileAsync(); 
        // Dosya uzerinde islemler
    }
}
 
public interface IFileProvider
{
    Task<string> SelectFileAsync();
}
Portable class libraryi yazdıktan sonra bu kütüphaneyi kullanan Windows 8 uygulaması da portable classın belirlediği interface'te bir file provider yaratacak ve bu providerı portable class library içerisine Foo metodunu çağırırken parametre olarak geçecek.
public class WindowsFileProvider : IFileProvider
{
    public async System.Threading.Tasks.Task<string> SelectFileAsync()
    {
        FileOpenPicker picker = new FileOpenPicker();
        var file = await picker.PickSingleFileAsync();
        return file.Path;
    }
}
 
public class MyApp
{
    WindowsFileProvider fileProvider = new WindowsFileProvider();
 
    public async Task ExecuteAsync()
    {
        MyLibrary library = new MyLibrary();
        await library.Foo(fileProvider);
    }
}

Şimdi gelelim shared projects tarafına. Bakalım o tarafta işler nasıl yürüyor.

Universal App Shared Projects

Visual Studio 2013 Update 2 ile beraber gelen Universal App konsepti ve Shared projectler aslında portable class librarylerde bulunan bazı sıkıntıları çözüyorlar.

Aslında öncelikli olarak belirtmem lazım ki portable class library ile shared projectler tamamen ayrı konseptler. Shared projectler aslında universal app içerisinde bulunan ve universal app'in farklı platformlarda çalışacak uygulamaları arasında paylaştırılacak olan assetleri ve kodları bulunduran kısım.

Shared projectleri aslında biraz daha açarsak temel anlamda Visual Studio içerisinde uzun zamandan beri bulunan file link kavramına benziyorlar. Aslında daha yukarı çıkarak bakarsak file link yapısının biraz daha gelişmiş, derlenmiş toparlanmış hali. Yani siz bir dosyayı birden fazla projede de kullanılacak şekilde saklıyorsunuz. Ancak dosyanın fiziksel olarak tek bir kopyası tutuluyor.

Şimdi gelelim shared code içerisinde platform spesifik kod yazma kısmına. Peki biz yukarıdaki dosya açma işlemini shared code içerisinde yapmak isteseydik nasıl yapacaktık ?

Shared project içerisinde platform spesifik kod yazmak istediğimizde #if directivelerini kullanarak olarak platform spesifik kodları yazabiliyoruz. Örneğin,

public class MyLib
{
    public async Task Foo()
    {
        string filePath = String.Empty;
#if WINDOWS_APP
        FileOpenPicker picker = new FileOpenPicker();
        var file = await picker.PickSingleFileAsync();
        filePath = file.Path;
#endif
#if WINDOWS_PHONE_APP
        //Windows Phone spesfik kodlar
#endif
 
        // Dosya uzerinde ortak islemler
    }
}

Gördüğünüz gibi platform spesifik kodları if directiveleri içerisinde yazdık. Yani bizim kodumuz Windows Store App için derlendiğine #if WINDOWS_APP directive içerisinde olan kodlar kodumuzun içerisinde olacak. Aynı şekilde Windows Phone için derlediğinde de #if WINDOWS_PHONE_APP directive'i içerisinde bulunan kodlar yine source kod içerisinde olacak.

Ancak gördüğünüz gibi uygulamanız büyükdükçe #if directive 'leriniz artacak ve kodunuzun yönetimi de oldukça zorlaşacaktır. Şimdi isterseniz ortalığı toparlayalım ve bu iki çözümünde avantajlarına ve dezavantajlarına kısaca bir bakalım.

Portable Class Libraries vs Universal App Shared Projects

Portable class librarylere baktığımızda yapılarının oldukça basit olduğunu görüyoruz. Yani sadece desteklediğiniz platformlardaki kesişen kütüphaneleri kullanabiliyorsunuz ve ötesi yok. Bu kadar basit. Elinizdeki imkanlarla ilerlemek zorundasınız. Bu da aslında bir anlamda size basitlik sağlıyor. Yani kodunuz içerisinde platform spesifik kod yazmıyorsunuz. Ancak platform spesifik kod yazmak istediğinizde de abstraction yaparak dependency injection, IoC container kullanmanız gerekiyor. Bu nedenle portable class libraryler birden fazla platformu destekleyen algoritmalar veya kütüphaneler(SDK) için ideal ortam.

Shared projects tarafında ise portable class library tarafındaki platform spesifik kod yazamama sıkıntısı çözülüyor. Ancak bu çözüm de hoş bir çözüm değil. En azından bana göre :) Uygulamanız büyüdükçe platform spesifik kodlar da büyüyebilir ve karışabilir. Böylece kodunuzun bakımı da zorlaşır. Ancak bir yandan da aynı işlemleri portable class libraries ile yaptığınızda da hem abstraction vs.. derken işiniz daha da uzuyor hem de kodunuz yine karmaşıklaşıyor. Bu nedenle en basit çözüm Universal App geliştirirken shared projectlerle ilerlemek.

Ancak gördüğünüz gibi cross platform uygulama geliştirme konusunda kod paylaşımı hala  daha tam anlamıyla süper bir çözümle başarılmış değil. Şu anki çözümler sadece acımızı bir nebze hafifletiyor.

Umarım faydalı olmuştur.



Yorum Gönder