Berk Akademi
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

C#'ta Try-Catch-Finally ve Exception Handling Mantığı Nasıl Çalışır?

Yazar: Berk Keskin 29.08.2026 ~13 dk okuma 3 Okunma
csharp-try-catch-finally-exception-handling

C#'ta exception handling, bir programın çalışması sırasında ortaya çıkan beklenmedik durumları (istisnaları) yakalayıp kontrollü biçimde yönetme mekanizmasıdır; temelinde try-catch-finally blok yapısı bulunur ve amacı programın aniden çökmesini önlemek değil, hatayı öngörülebilir ve güvenli bir şekilde ele almaktır. Sıfıra bölme, dosya bulunamaması, ağ bağlantısının kopması gibi çalışma zamanı hataları try bloğu içinde denenir, catch bloğunda yakalanır, finally bloğunda ise sonuç ne olursa olsun çalışması gereken temizlik kodu yazılır. Java'dan C#'a geçiş yapan bir öğrenci için bu yapı görsel olarak neredeyse birebir tanıdık gelir, ancak exception modelinin işleyiş mantığında köklü bir fark vardır ve bu fark, kodun nasıl yazılması gerektiğini doğrudan etkiler.

C#'ta Exception Handling Nedir ve Neden Gereklidir?

Exception (istisna), bir programın normal akışını kesintiye uğratan ve çalışma zamanında ortaya çıkan olağandışı bir durumdur. Kullanıcının olmayan bir dosyayı açmaya çalışması, bir sayının sıfıra bölünmesi, bir dizinin sınırları dışına erişilmesi gibi durumlar exception fırlatır (throw eder). Exception handling ise bu durumları önceden tahmin edip programın kontrollü bir şekilde tepki vermesini sağlayan yapıdır; hangi hataların yakalanacağı ve nasıl yönetileceği geliştiricinin sorumluluğundadır. Burada kritik ayrım şudur: programın çökmesini engellemek ile hatayı doğru yönetmek aynı şey değildir. Bir catch bloğu yazıp hatayı sessizce yutmak, programı ayakta tutabilir ama altta yatan sorunu gizler ve ileride çok daha ciddi veri bütünlüğü problemlerine yol açabilir. Doğru yaklaşım, hangi hatanın gerçekten beklenebilir olduğunu belirlemek, o hatayı anlamlı bir şekilde işlemek (loglamak, kullanıcıya bilgi vermek, alternatif bir akış sunmak) ve beklenmeyen hataların ise fark edilmesine izin vermektir. Java'dan geçiş yapan bir okuyucu için bu konunun ilerleyen bölümlerde farklı çalışacağını baştan belirtmek gerekir: Java'da alışılmış olan derleyicinin hata yakalamayı zorunlu kılması davranışı C#'ta yoktur. Bu, C#'ın hata yönetimini daha "gevşek" değil, farklı bir disiplin gerektiren bir model haline getirir; bu farkın pratik sonuçları ilerleyen bölümde detaylandırılacaktır.

Try-Catch-Finally Yapısının Temel Çalışma Mantığı

C#'ta try-catch-finally yapısı belirli bir sırayla çalışır. Önce try bloğu içindeki kod çalıştırılır; bir hata oluşursa akış anında kesilir ve uygun catch bloğuna atlanır. Catch bloğu hatayı işledikten sonra, tanımlanmışsa finally bloğu çalışır. Finally bloğunun en önemli özelliği, try bloğunda hata olsun ya da olmasın, hatta catch içinde return çalıştırılsa bile her koşulda çalışmasıdır; bu yüzden dosya kapatma, bağlantı sonlandırma gibi temizlik işlemleri için idealdir. Aşağıdaki basit örnek, sıfıra bölme senaryosuyla bu akışı gösterir:

try
{
    int a = 10;
    int b = 0;
    int sonuc = a / b;
    Console.WriteLine("Sonuç: " + sonuc);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("Hata: Bir sayı sıfıra bölünemez.");
}
finally
{
    Console.WriteLine("İşlem tamamlandı, kaynaklar serbest bırakılıyor.");
}

Bu örnekte a / b işlemi bir DivideByZeroException fırlatır, catch bloğu bu hatayı yakalayıp kullanıcıya anlamlı bir mesaj verir ve ardından finally bloğu, hata yakalansa da yakalanmasa da mutlaka çalışır. Eğer catch bloğu tanımlanan exception türüyle uyuşmayan bir hata oluşursa ya da hiç catch bloğu yazılmamışsa, exception yakalanmaz ve program çalışma zamanında sonlanır; bu durumda kullanıcı genellikle bir hata mesajı (stack trace) ile karşılaşır ve uygulama beklenmedik şekilde kapanır. Bu yüzden hangi exception türlerinin bekleneceğini önceden düşünmek, try-catch-finally yapısının etkili kullanılmasının temelidir.

C#'ın Java'dan Farkı: Tamamen Unchecked Exception Modeli

C#'ın Java'dan Farkı: Tamamen Unchecked Exception Modeli

Java'da exception'lar iki kategoriye ayrılır: checked exception'lar (örneğin IOException) derleyici tarafından zorunlu tutulur ve bir metot bunları fırlatıyorsa ya try-catch ile yakalanmalı ya da metot imzasında throws ile bildirilmelidir; unchecked exception'lar (örneğin RuntimeException alt sınıfları) ise bu zorunluluğa tabi değildir. C# bu ayrımı benimsemez; C#'taki tüm exception türleri, Java'nın unchecked exception'larına benzer şekilde davranır ve derleyici hiçbir exception için yakalama zorunluluğu koymaz. Bunun pratik sonuçları somuttur. Bir C# metodunun hangi exception'ları fırlatabileceği metot imzasında görünmez; Java'daki throws IOException gibi bir bildirim mekanizması C#'ta yoktur. Bu da bir metodun içinde dosya okuma, ağ isteği veya veritabanı işlemi yapılıp yapılmadığını, dolayısıyla hangi hataların beklenmesi gerektiğini yalnızca dokümantasyondan veya kaynak kodu incelemekten anlayabileceğiniz anlamına gelir. Sonuç olarak bir hata, geliştirme aşamasında değil, çalışma zamanında (runtime) beklenmedik bir anda ortaya çıkabilir; derleyici bu konuda geliştiriciyi uyarmaz. Bu fark kod okunabilirliği ve disiplinli hata yönetimi açısından iki yönlü bir etki yaratır. Java'nın checked exception zorunluluğu, geliştiriciyi olası hataları düşünmeye mecbur bırakırken bazen gereksiz boilerplate catch bloklarına da yol açabilir. C#'ın unchecked modeli ise kodu daha az zorlayıcı hale getirirken, hangi hataların yakalanması gerektiğini tamamen geliştiricinin dikkatine ve deneyimine bırakır. Java'dan gelen bir geliştiricinin Java'daki exception yönetimi pratiğiyle kurduğu refleksleri C#'a taşırken, artık derleyicinin bu konuda bir güvenlik ağı sunmadığını bilerek kod yazması, sağlıklı bir alışkanlık geliştirmesi açısından belirleyicidir. Bu nedenle C#'ta hangi metodun hangi exception'ları fırlatabileceğini bilmek, dokümantasyon okuma ve savunmacı programlama alışkanlığını daha kritik hale getirir.

Neden Genel catch(Exception) Kullanımı Sorun Yaratır?

C#'ın tamamen unchecked exception modeli, derleyicinin hiçbir zaman "bu metodu şu istisnalarla sarmalı" diye zorlamaması anlamına gelir. Bu özgürlük, ilk bakışta rahatlatıcı görünse de pratikte tehlikeli bir alışkanlığı besler: geliştiricinin, hangi hatanın nereden geleceğini düşünmeden doğrudan catch (Exception ex) yazıp geçmesi. Derleyici zorlamadığı için bu kestirme yol her zaman elle uzanılabilir mesafededir ve zamanla neredeyse otomatik bir refleks hâline gelir.

Sorun, bu genel yakalamanın sadece beklenen hataları değil, kodun mantığındaki gerçek hataları da (örneğin bir NullReferenceException ya da bir dizi sınır ihlali) sessizce yutmasıdır. Program çökmez, ama yanlış bir durumda çalışmaya devam eder; log dosyasında belirsiz bir mesaj kalır ya da hiç kalmaz. Debug sürecinde geliştirici, hatanın nerede oluştuğunu bulmak için saatler harcar çünkü hatanın türü ve konumu hakkında hiçbir ipucu yoktur. Bu noktada catch bloğunun genişliği ile hata ayıklama süresi ters orantılı hâle gelir: ne kadar genel yakalarsanız, sorunu bulmak o kadar uzun sürer.

Exception Türü Ne Zaman Oluşur Doğru Yaklaşım
FileNotFoundException Belirtilen yolda dosya bulunamadığında Dosya varlığını önceden kontrol et veya bu türü ayrı catch bloğuyla yakala
IOException Dosya okuma/yazma sırasında disk veya izin sorunu oluştuğunda Kaynak erişim hatasını ayrı ele al, kullanıcıya anlamlı mesaj ver
NullReferenceException Başlatılmamış bir nesne referansına erişildiğinde Genellikle kod hatasıdır; yakalamak yerine null kontrolüyle önlenmeli
Exception (genel) Beklenmeyen, sınıflandırılmamış her türlü hata Yalnızca en dış katmanda, loglama amacıyla son çare olarak kullanılmalı

Genel catch(Exception) tamamen yasaklanacak bir yapı değildir; uygulamanın en dış katmanında, örneğin bir API'nin merkezi hata middleware'inde ya da uygulama genelinde son bir güvenlik ağı olarak loglama amacıyla kullanılması makul kabul edilir. Ancak bu, iş mantığının içindeki her metotta rutin bir savunma aracı olarak kullanılmamalıdır. Bu ayrımı erken öğrenmek isteyenler için birebir C# ve yazılım dersleri kapsamında gerçek proje senaryoları üzerinden hata yönetimi pratiği yapılabilir.

Catch Bloklarını Daraltma: Spesifik Exception Türleriyle Çalışma

Bir try bloğunda birden fazla catch kullanılacaksa, sıralama rastgele değildir: en spesifik exception türü her zaman en üstte, en genel tür ise en altta yer almalıdır. Bunun nedeni, C#'ın çalışma zamanında catch bloklarını yukarıdan aşağıya sırayla kontrol etmesi ve tür uyumu bulduğu ilk bloğu çalıştırmasıdır. Genel tür yukarıda olursa, ondan sonra gelen daha spesifik bloklara asla sıra gelmez.

Pratikte sağlıklı bir catch zinciri kurmak için izlenebilecek adımlar şu şekilde sıralanabilir:

  1. Metodun hangi işlemi yaptığını ve bu işlemin gerçekçi olarak hangi hata türlerini üretebileceğini belirleyin (dosya işlemi, ağ çağrısı, veri dönüşümü gibi).
  2. Beklenen en somut hatayı, o hatanın kendi sınıfıyla (örneğin FormatException veya FileNotFoundException) yakalayın; böylece hata mesajınız ve müdahale kodunuz o duruma özel olur.
  3. Aynı blokta birden fazla farklı hata senaryosu bekleniyorsa, her biri için ayrı bir catch bloğu ekleyin; her blok kendi türüne özgü bir çözüm veya kullanıcı mesajı üretmelidir.
  4. Zincirin en sonuna, öngörülmeyen durumları yakalayıp loglamak amacıyla genel bir catch (Exception ex) bloğu koyun; bu blok asla sessiz kalmamalı, en azından hatayı kaydetmelidir.

Bu sıralama tersine çevrilirse, yani genel Exception bloğu daha spesifik bir türden önce yazılırsa, C# derleyicisi bunu çalışma zamanına bırakmaz; derleme aşamasında "erişilemez catch bloğu" (unreachable catch clause) hatası vererek kodun derlenmesini engeller. Bu davranış, Java'dan geçiş yapan öğrenciler için faydalı bir güvenlik katmanıdır çünkü unchecked model içinde bile derleyici en azından mantıksal sıralama hatalarını erken aşamada yakalar.

Özel (Custom) Exception Sınıfları Oluşturma

Özel (Custom) Exception Sınıfları Oluşturma

Framework'ün sunduğu hazır exception türleri (IOException, FormatException, InvalidOperationException gibi) teknik hataları karşılar, ancak bir uygulamanın kendi iş kurallarını ihlal eden durumları anlatmakta yetersiz kalır. Örneğin bir bankacılık uygulamasında "bakiye yetersiz" ya da bir stok sisteminde "ürün stokta yok" gibi durumlar teknik bir hata değil, domain'e özgü bir kuraldır. Bu tür durumlar için özel exception sınıfları yazmak, hem kodun okunabilirliğini hem de hata ayıklamayı belirgin biçimde kolaylaştırır.

Özel bir exception sınıfı oluşturmanın temel mantığı, Exception sınıfından türetmek ve genellikle mesaj taşıyan bir kurucu metot tanımlamaktır. Bu sayede özel sınıf, .NET'in standart exception altyapısıyla (stack trace, mesaj, inner exception zinciri) tam uyumlu çalışırken, çağıran kodun bu hatayı kendi türüyle ayrı bir catch bloğunda yakalamasına da imkân tanır:

public class InsufficientBalanceException : Exception
{
    public InsufficientBalanceException(string message) : base(message) { }
}

public class Account
{
    public decimal Balance { get; private set; }

    public void Withdraw(decimal amount)
    {
        if (amount > Balance)
        {
            throw new InsufficientBalanceException(
                "Bakiye yetersiz, çekim işlemi gerçekleştirilemedi.");
        }
        Balance -= amount;
    }
}

Bu yaklaşımın en somut faydası, hata mesajının kod içinde nereden geldiğinin açıkça belli olmasıdır; bir catch (InsufficientBalanceException ex) bloğu gören geliştirici, hatanın teknik değil iş kuralına dayalı olduğunu anında anlar. Genel Exception ile karşılaştırıldığında bu, hem loglarda hem de hata ayıklama sürecinde zaman kazandırır. Bu tür tasarım kararlarını gerçek projeler üzerinde uygulamalı görmek isteyenler birebir Java ve C# özel dersleri ile kendi kod tabanlarında pratik yapabilir.

using Deyimi ve IDisposable ile Kaynak Yönetimi

Dosya akışları, veritabanı bağlantıları, ağ soketleri gibi kaynaklar .NET çalışma zamanının otomatik olarak yönetmediği, yani yönetilmeyen (unmanaged) kaynaklara bağlı nesnelerdir. Bir dosya akışını açtığınızda işletim sisteminden bir tanıtıcı (handle) alırsınız; bu tanıtıcıyı elle kapatmazsanız, çöp toplayıcı nesneyi bellekten temizlese bile alttaki sistem kaynağı bir süre daha meşgul kalabilir. Bu yüzden dosya, bağlantı veya akış kullanan her kod bloğunda kaynağı kapatmayı garanti altına almak gerekir.

Önceki bölümde gördüğünüz finally bloğu bu garantiyi sağlayan genel yöntemdir, ama her seferinde Close() veya Dispose() çağrısını elle yazmak hem tekrarlı hem hataya açıktır. C#'ta IDisposable arayüzünü uygulayan sınıflar (FileStream, StreamReader, SqlConnection gibi) için using deyimi, aynı işi derleyicinin ürettiği bir try/finally bloğuna dönüştürerek kaynağı kapsam dışına çıkar çıkmaz otomatik serbest bırakır. Aşağıdaki örnek, bir metin dosyasının using ile açılıp okunmasını ve blok bittiğinde otomatik kapatılmasını gösterir:

using (StreamReader reader = new StreamReader("veri.txt"))
{
    string satir = reader.ReadLine();
    Console.WriteLine(satir);
} // reader.Dispose() burada otomatik çağrılır

Burada dikkat edilmesi gereken nokta, using'in yalnızca kaynağın kapatılmasını garanti etmesidir; olası bir FileNotFoundException veya IOException'ı yakalamaz. Bu yüzden using ile try-catch genellikle birlikte kullanılır: using kaynağın güvenli kapanmasını üstlenirken, çevresindeki try-catch olası hataları karşılar. Kaynak kapatma dışında ek bir temizlik adımı (örneğin bir log yazma veya sayaç güncelleme) gerekiyorsa, using'i ayrı bir try-finally ile birlikte kullanmak da mantıklı bir tercihtir; iki yapı birbirini dışlamaz, tamamlar.

Dosya Okuma Örneğiyle Uçtan Uca Güvenli Hata Yönetimi

Şimdiye kadar ele alınan üç kavramı -catch bloklarını daraltma, using ile kaynak yönetimi ve gerektiğinde özel exception sınıfı- tek bir örnekte birleştirelim. Aşağıdaki kod, var olmayan veya erişilemeyen bir dosyayı okumaya çalışırken oluşabilecek durumları ayrı ayrı ele alır:

public string DosyaOku(string yol)
{
    try
    {
        using (StreamReader reader = new StreamReader(yol))
        {
            return reader.ReadToEnd();
        }
    }
    catch (FileNotFoundException ex)
    {
        Console.WriteLine("Dosya bulunamadı: " + ex.FileName);
        return null;
    }
    catch (IOException ex)
    {
        Console.WriteLine("Dosya okunurken bir G/Ç hatası oluştu: " + ex.Message);
        return null;
    }
    finally
    {
        Console.WriteLine("Dosya okuma denemesi tamamlandı.");
    }
}

Bu kodda using bloğu, işlem başarılı da olsa hata da fırlatılsa StreamReader nesnesinin kapatılmasını garanti eder. catch blokları genel bir Exception yerine FileNotFoundException ve IOException gibi spesifik türlerle daraltılmıştır; böylece dosyanın bulunamaması ile diskin dolu olması veya dosyanın başka bir işlem tarafından kilitlenmesi gibi farklı senaryolar birbirinden ayrı, anlamlı biçimde ele alınır. finally bloğu ise hangi yol izlenirse izlensin çalışacak ortak bir kapanış adımını (burada basit bir log satırı) üstlenir.

Gerçek bir uygulamada bu iskelet kolayca genişletilebilir: hata mesajları kullanıcıya gösterilecekse konsol yazısı yerine bir arayüz bildirimine, log satırı bir dosya veya izleme sistemine yönlendirilebilir. Dosyanın içeriği belirli bir formata (örneğin JSON veya CSV) uymuyorsa, önceki bölümde anlatıldığı gibi bir GecersizVeriFormatiException türetip anlamlı bir hata mesajıyla fırlatmak, çağıran kodun sorunu daha net anlamasını sağlar. Aynı mantık, dosya yerine bir ağ isteği veya veritabanı sorgusu için de birebir uygulanabilir; değişen yalnızca yakalanacak exception türleri ve kaynağın nasıl kapatıldığıdır.

C# Exception Handling Becerinizi Nasıl Pekiştirebilirsiniz?

Bu yazıda ele alınan kavramlar birbirini tamamlayan bir bütün oluşturur: try-catch-finally yapısının çalışma sırası, C#'ın tamamen unchecked exception modeli, genel catch(Exception) kullanımının neden risk taşıdığı, catch bloklarını spesifik türlerle daraltmanın değeri, gerektiğinde özel exception sınıfları tanımlama ve using ile kaynakları güvenli biçimde kapatma. Bu kavramları tek tek bilmek yeterli değildir; asıl beceri, bir kod yazarken hangi hatanın nerede, hangi türle ve hangi kapsamda yakalanması gerektiğine doğru karar verebilmektir.

Bu tür kararları otururken değil, pratik yaparken öğrenirsiniz. Kısa kod parçaları üzerinde farklı exception senaryolarını bilerek tetiklemek, hangi catch bloğunun devreye girdiğini ve finally'nin ne zaman çalıştığını gözlemlemek, teorik bilgiyi kalıcı hale getirir. Bilginizi düzenli aralıklarla ölçmek de bu sürecin ayrılmaz bir parçasıdır; nerede eksik kaldığınızı görmeden ilerlemek, yanlış öğrenilen bir alışkanlığı pekiştirme riski taşır.

Konuyu ne kadar özümsediğinizi kısa yoldan görmek isterseniz, C# bilgi seviyesi ölçüm testi ile exception handling dahil temel C# konularındaki hakimiyetinizi hızlıca değerlendirebilirsiniz. Çıkan sonuca göre hangi konuları tekrar etmeniz gerektiğini netleştirmek, sonraki öğrenme adımlarınızı daha isabetli planlamanızı sağlar.

Sık Sorulan Sorular

C#'ta try-catch-finally bloklarının çalışma sırası nasıldır?

Önce try bloğu çalıştırılır; bir hata oluşursa uygun catch bloğu devreye girer, hata oluşmazsa catch atlanır. Her iki durumda da en son finally bloğu çalışır; bu blok hata olsun olmasın, hatta metottan erken return yapılsa bile çalışmaya devam eder.

C# neden Java gibi checked exception kullanmaz?

C#, tüm exception türlerini unchecked olarak ele alır; yani derleyici bir metodun hangi exception'ları fırlatabileceğini imzasında zorunlu kılmaz ve çağıran kodu try-catch yazmaya mecbur bırakmaz. Bu, geliştiriciye esneklik tanırken hangi hataların yakalanması gerektiğine dair kararı tamamen geliştiricinin dikkatine bırakır.

catch(Exception) kullanmak her zaman yanlış mıdır?

Hayır, ancak yaygın kullanımı sorunludur. Bir uygulamanın en dış katmanında beklenmedik hataları loglamak veya kullanıcıya genel bir hata mesajı göstermek için tek bir genel catch(Exception) makul olabilir; ancak iç mantıkta her hatayı aynı torbaya atmak, farklı hata türlerinin farklı şekilde ele alınması gerektiğinde sorun yaratır.

Özel exception sınıfı ne zaman oluşturulmalıdır?

Framework'ün sunduğu hazır exception türleri (FileNotFoundException, IOException, ArgumentException vb.) durumu yeterince anlamlı biçimde ifade etmiyorsa ve uygulamaya özgü bir iş kuralı ihlali söz konusuysa özel bir exception sınıfı tanımlamak, hem hatanın kaynağını hem çağıran kodun ne yapması gerektiğini netleştirir.

using deyimi try-finally'nin yerini tamamen alır mı?

Yalnızca kaynağı kapatma sorumluluğu için evet, ancak using bir hatayı yakalamaz. Olası bir istisnayı ele almak istiyorsanız using'i yine bir try-catch ile birlikte kullanmanız gerekir; ek bir temizlik adımı gerekiyorsa ayrı bir finally ile de birleştirilebilir.

finally bloğu hangi durumlarda çalışmaz?

finally bloğu neredeyse her koşulda çalışır; ancak işlemin çalıştığı süreç aniden sonlandırılırsa (örneğin uygulamanın beklenmedik biçimde kapanması veya işletim sistemi seviyesinde bir kesinti yaşanması gibi istisnai durumlarda) finally bloğunun tamamlanma garantisi ortadan kalkabilir.

C# öğrenirken exception handling konusunu pekiştirmek için ne yapılabilir?

Farklı hata senaryolarını (dosya bulunamaması, geçersiz veri, bağlantı kopması gibi) kendi kısa kod örnekleriniz üzerinde bilinçli olarak tetikleyip hangi catch bloğunun çalıştığını gözlemlemek, ardından öğrendiklerinizi kısa testlerle ölçmek kalıcı öğrenmeyi destekler.

C#'ta exception handling mantığını sağlam kurmak, yalnızca hataları yakalamak değil, hangi hatanın hangi seviyede ve hangi türle ele alınacağına doğru karar vermektir. Bu yazıda işlenen kavramları daha derinlemesine, canlı örnekler ve geri bildirimle pekiştirmek isterseniz 1-1 özel Java dersleri kapsamında nesne yönelimli programlama ve hata yönetimi konularını karşılaştırmalı biçimde çalışabilirsiniz.

Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 300'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara