Sitemap

Uygulama Programlama Arayüzleri Nedir?

8 min readMay 10, 2025

API’ları yani Uygulama Programlama Arayüzlerini tanıyoruz.

Giriş

Dijitalleşen dünyada, akıllı cihazlara sahip olan çok sayıda insan, teknik bilgisi olmasa bile karmaşık yazılımları düzenli olarak kullanıyor. Bu nedenle kullanıcı arayüzlerinin hem anlaşılır hem de güvenilir olması gerekiyor. Örneğin, Amazon’un alışveriş sitesi oldukça kullanıcı dostu görünse de arkasında dünya çapında binlerce makine ve mühendis tarafından yönetilen devasa bir sistem yer alıyor. Kullanıcıların yazılımla etkileşimi genellikle bu sistemin yalnızca görünen kısmıdır.

Yazılım mühendisleri ve veri bilimciler ise daha teknik bir şekilde, uygulama programlama arayüzleri (API’lar) aracılığıyla bilgisayarlarla etkileşim kurmaktadırlar. API diyince aklınızda REST backend servisleri geliyor olabilir ancak API’lar bundan fazlasıdır. API’lar, bir yazılım bileşeninin başka bir bileşenle nasıl iletişim kuracağını belirleyen kurallardır. API’lar kullanıma/hizmete açılmış kodlardır ve bu nedenle sadece çalışmaktan fazlası olmalıdırlar.

Bu yazı, mühendis ve bilim insanlarına yönelik olup yaygın API kullanımlarına genel bir bakış sunmayı ve iyi bir uygulama programlama arayüzü tasarımının nasıl olması gerektiğini öğretmeyi amaçlamaktadır. Python’da iyi ve kötü API tasarım örnekleri üzerinden ilerlenerek kullanıcıya bu alandaki eleştirel bakış açısını geliştirme yetkinliği kazandırılacaktır. Martin Fowler’ın dediği gibi: “Herkes, bilgisayarın anlayacağı bir kod yazabilir ancak iyi programcılar, insanların anlayacağı kodlar yazabilirler.

Yazılım ve Hizmetlerle Etkileşim

Modern bilgisayarlar son derece karmaşıktır. Örneğin, Python’da veri analizi yaparken kodunuzun makine diline dönüşümünü ya da CPU’nun nasıl çalıştığını düşünmeden sadece işinize odaklabilmektesiniz. Kodunuzun doğru çalıştığını API’lar (Uygulama Programlama Arayüzleri) sayesinde varsayarsınız. API’lar, yazılım bileşenleriyle etkileşim kurmayı sağlar; yapılan çağrıları, beklenen veri formatlarını ve davranış kurallarını tanımlarlar.

Örneğin, Python’da import komutu üç şekilde kullanılır: Bir modülün tamamını ve bir modülden belirli bir özelliği almak veya modüle takma ad vermek şeklinde. Import komutu ile eklediğiniz Python kütüphaneleri sayesinde başkalarının geliştirdiği ctime() fonksiyonlarını kullanarak sistem zamanı gibi özellikleri kullanabilirsiniz.

API terimi ilk kez 1960’larda ortaya atılmıştır ve başlangıçta sadece kullanıcı arayüzleri için kullanılmıştır. Zamanla veri tabanı yönetim sistemlerine, ardından tüm yazılım etkileşimlerine yayılmıştır. 1990’larda tüm yazılım görevlerini kapsayacak şekilde tekrar tanımlanmıştır. Web’in yaygınlaşmasıyla web API’ları doğmuştur. Amazon ve Salesforce gibi firmalar bu alanda öncülük etmiş, AWS (Amazon Web Services) gibi hizmetlerle içerik ve altyapı paylaşımı başlatmıştır. 2000’lerin ortasında sosyal medya API’ları (Facebook, Twitter) geliştiricilere platform verilerine erişim sunmuştur. Bulut tabanlı API’larla geliştiriciler, örneğin EC2 ve S3 kullanarak uygulamalarını internette barındırabilmiştir. IoT (Nesnelerin İnterneti) ile cihazlar API’larla birbirine bağlanmaya başlamıştır (ör. Alexa, Fitbit).

API’lar, sağlayıcılar ile kullanıcılar (bireyler ya da makineler) arasında bir sözleşme gibidir. Bu sözleşmelerin belirli versiyonları olur (ör. GitHub API v3). Yeni özellikler aynı sürümde eklense de büyük değişiklikler yeni sürümlere aktarılır. Böylece kullanıcılar değişimlere hazırlanabilir. API’lar ayrıca kullanımdan kaldırılmadan önce kullanım dışı bırakılırlar (deprecation) ve bu da geliştiricilere geçiş süresi sağlar.

API belgeleri (dökümantasyon), anlaşılabilirliği sağlamak için kritik önemdedir. Açıkça yazılmayan her API çağrısı yanlış anlaşılabilir. Belgeler, bir nevi API’ın kendisidir. Gereksinim mühendisliği çerçevesinde önceden detaylı olarak belirlenmeleri idealdir.

API’ların güvenliği ve yönetişimi önemlidir. Dış API’lara bağımlı firmalar, bu API’ların performansını izlemek zorundadır. İç sistemlerini dış API değişimlerine göre güncellemelidirler. API sağlayıcıları da güvenlik önlemleri almalı ve erişim haklarını dikkatle belirlemelidir. API’lar üç şekilde yayımlanır: özel (sadece iç kullanım), ortak (belirli ortaklarla), genel (herkese açık). Ancak “genel” terimi “ücretsiz” anlamına gelmez.

API türleri çok çeşitlidir. Donanım seviyesinden uygulama seviyesine kadar katmanlı bir yapı sunarlar. Örneğin, POSIX standardı, işletim sistemleri için API’lar belirler. OpenGL ve OpenCL, grafik ve paralel işlem uygulamaları için çapraz platform API’lardır. CUDA ise Nvidia’nın GPU’lar için geliştirdiği özel bir API’dir ve derin öğrenme gibi alanlarda sık kullanılır.

Komut satırı arayüzleri (CLI), OS API’larını metin tabanlı komutlarla kullanmanıza olanak sağlar. Python’un CLI araçları arasında python komutu ve paket yöneticisi pip yer alır. CLI ile Python sürümünü sorgulayabilir (python -V), veya modül kurabilir (pip install pandas).

Bu katmanlı yapılar sayesinde geliştiriciler donanım detaylarını bilmeden üretken olabilir. API’lar, yazılım geliştirmede temel yapı taşlarıdır ve neredeyse tüm modern dijital altyapının omurgasını oluştururlar.

API Tasarım İlkeleri

Bu metin, API tasarımının iyi ve kötü örneklerini karşılaştırarak açıklayan, kullanıcı deneyimini ve yazılım mühendisliğinde dikkat edilmesi gereken temel ilkeleri ele alan kapsamlı bir değerlendirmedir. Özet şu şekildedir:

API Tasarım İlkeleri: API yazarken en önemli hedef, kullanıcı tarafından kolayca anlaşılabilir olmasıdır. Bu bağlamda, iyi ve kötü tasarım örnekleriyle ilkeler açıklanır.

Kötü API Örneği Ray: Ray kütüphanesi ile yapılan bir örnekte, TensorFlow yüklü olmadığında geç bir hata vererek kullanıcıyı yanıltır. Kullanıcı, hatayı anlamak için uzun çıktıların içinde arama yapmak zorunda kalır. Bu, hatanın geç ortaya çıkması, mesajın belirsizliği ve kullanıcıyı bilgilendirmeme gibi hatalı API tasarımı unsurlarını gösterir.

İyi API Örneği Keras: Keras, TensorFlow eksikliğini hemen bildirir ve çözüm önerisi sunar. Bu, kullanıcı deneyimini geliştiren, açık ve okunabilir bir hata mesajı ile iyi API tasarımının örneğidir.

Zen of Python: Python’un tasarım felsefesini yansıtan “Zen of Python”, API tasarımı için rehber niteliğindedir. Bazı ilkeler:

  • Güzel, çirkinden iyidir.
  • Bariz, gizliden iyidir.
  • Basit, karmaşıktan iyidir; karmaşık, karma karışık olandan iyidir.
  • Okunabilirlik önemlidir.
  • Hatalar sessizce geçmemelidir.
  • Belirsizlik karşısında tahminden kaçınılmalıdır.
  • Bir şeyi yapmanın tek ve tercihen sadece tek bir belirgin yolu olmalıdır.
  • Şimdi, hiç olmamasından iyidir.
  • Uygulamanın açıklaması zorsa kötü bir fikirdir, açıklaması kolaysa iyi bir fikir olabilir.
  • Ad alanları (namespaces) harika bir fikirdir.

Arayüz ve Uygulama Ayrımı: API arayüzleri, kullanıcıların kodun iç detaylarını bilmeden kullanabilmesi için tasarlanır. Java gibi dillerde bu ayrım zorunlu iken, Python’da böyle bir ayrım dil tarafından zorlanmaz ancak yine de dikkat edilmesi gereken bir ilkedir. Arayüz, kodun dışa açık kısmı (yüzey alanı) olarak görülmelidir.

Soyutlama: Doğru soyutlamalar, API’ın kullanımını kolaylaştırır. Keras örneğinde, model ve katman gibi doğal kavramlarla sezgisel bir kullanım sunulur. Her ne kadar tüm soyutlamalar zaman zaman “sızdırsa” da (yani detaylara inmek gerekse de), iyi soyutlamalar büyük fayda sağlar.

Hata Yönetimi:

  • Hatalar erken ve hızlı ortaya çıkmalıdır.
  • Hata mesajları açık, okunabilir ve çözüm önerisi içermelidir.
  • Kullanıcıya seviyeli mesajlar sunulmalıdır (örneğin, uyarılar, kaldırılacak fonksiyonlar hakkında bilgilendirme).

Âdet ve Yapılandırma: API’larda “Âdet > yapılandırma > kod” ilkesi önerilir. İyi varsayılan değerler sunmak, kullanıcıların API’ı hızlıca kullanmasını sağlar. Fonksiyonlara parametre vererek yapılandırmak, doğrudan kodla müdahale etmekten iyidir. İyi adlandırma kuralları ve sade sınıf adları, kodun anlaşılırlığını artırır.

Kullanıcı Deneyimi: Geliştirici deneyimi, kullanıcıyla empati kurmakla ilgilidir. API’ların tasarımında bilişsel yük, öğrenme eğrisi, yapıların tutarlılığı ve soyutlamaların sezgisel olup olmadığı gibi faktörler önemlidir. API’ların kullanıcıyla ne kadar iyi iletişim kurduğu, bunlara bağlıdır.

Belgelendirme: İyi bir API’ın başarısı için belgeler çok önemlidir:

  • Kod ve arayüzler belgelenmeli.
  • Girdi parametreleri ve dönüş değerleri açıklanmalı.
  • API’ın amaçlanan kullanımı net biçimde gösterilmelidir.

Python Kütüphanesi Oluşturma

Öncelikle, metin belgeleri üzerinde çalışan ve gelişmiş analizler yapan hayali bir şirket senaryosu ele alalım. Bu şirket, özel ve hızlı bir algoritmaya sahip olsun ve bu algoritmayı kullanıcılarla paylaşmadan bir hizmet olarak sunmak istesin. İlk adım, algoritmanın Python kütüphanesi şeklinde sunulmasıdır. Bu örnekte, algoritmanın yaptığı işlem basittir: Çok sayıda belge içindeki tüm kelimelerin sayımını yapmak.

Bu amaçla, Google’ın büyük veri işlemede önemli bir yeri olan MapReduce paradigmasının basitleştirilmiş bir versiyonu uygulanmış olsun. Üç adımda bu algoritma işlemektedir:

  1. Map: Belgelerdeki her kelime için (kelime, 1) anahtar-değer çiftleri üretilir.
  2. Group: Aynı anahtarlar (kelimeler) gruplanarak örneğin “lorem” kelimesi için [1,1,1,1,1] gibi bir liste oluşturulur.
  3. Reduce: Her grup içindeki değerler toplanarak toplam sıklık hesaplanır (örneğin “lorem”: 5).

Bu adımlar Python’da fonksiyonlarla gerçekleştirilmiştir:

  • map_function(): kelimeleri ayrıştırıp (kelime, 1) çiftleri üretir.
  • apply_map(): tüm belgeler için map_function uygulanır.
  • group_function(): aynı kelimeler gruplanır.
  • reduce_function(): değerler toplanır.
  • apply_reduce(): tüm gruplar için reduce_function uygulanır.

Örnek veri kümesi (dört kısa metin) ile algoritma çalıştırılmış ve beklenen çıktılar alınmıştır.

# --- Internal "Proprietary" Algorithm (Not directly exposed but called by API) ---
def map_function(text):
for word in text.lower().split():
yield word, 1

def apply_map(data):
map_results = []
for element in data:
for map_result in map_function(element):
map_results.append(map_result)
return map_results

def group_function(map_results):
group_results = dict()
for key, value in map_results:
if key not in group_results:
group_results[key] = []
group_results[key].append(value)
return group_results

def reduce_function(key, values):
total = 0
for count in values:
total += count
return key, total

def apply_reduce(group_results):
reduce_results = dict()
for key, values in group_results.items():
_, count = reduce_function(key, values)
reduce_results[key] = count
return reduce_results

# --- Naive API Function Exposed to Users ---
def count_words_naive(corpus): # Note: The text shows 'data_set' used internally here,
# which was a flaw pointed out by user feedback.
# A correct naive version would use 'corpus'.
# We'll stick to the text's direct code for the "before".
map_results = apply_map(data_set) # <--- Flaw: uses global 'data_set' not 'corpus'
group_results = group_function(map_results)
reduce_results = apply_reduce(group_results)
return reduce_results

# Example (internal) test data from the text
# text_1 = "Lorem ipsum dolor sit amet, consetetur et sadipscing elitr."
# text_1b = "Lorem ipsum dolor sit amet, consetetur et sadipscing elitr."
# text_2 = "At vero lorem et accusam et justo duo ipsum et ea rebum."
# text_2b = "At vero lorem et accusam et justo duo ipsum et ea rebum. At vero lorem et accusam et justo duo ipsum et ea rebum."
# data_set = [text_1, text_1b, text_2, text_2b]

Ancak, bu algoritmanın bir API’si henüz yoktur. Kullanıcılara yalnızca count_words_naive() adlı temel bir fonksiyon sunulmuştur. Bu fonksiyon doğrudan algoritmanın üç aşamasını çalıştırıp sonuç döndürmektedir. Kullanıcılardan gelen geri bildirimler doğrultusunda bu yaklaşımın eksikleri belirlenmiştir:

  • Fonksiyonun nasıl kullanılacağı açık değildir.
  • Belirsiz hatalar alınmaktadır.
  • Sonuçlar çok fazla veri içerebilir, filtreleme istenmektedir.
  • Kullanıcılar dosya yüklemek istiyor, Python içinde veri hazırlamak istemiyorlar.

Bu geri bildirimler ışığında, sonuçları filtreleyen bir filter_function(min_occurrences=4) fonksiyonu eklenmiştir. Ardından, daha kullanıcı dostu, tip kontrolü yapan, belgelenmiş ve yapılandırılabilir bir count_words() fonksiyonu yazılmıştır. Bu fonksiyon:

  • Belge dizisini parametre olarak alır.
  • Opsiyonel bir filtre (minimum frekans) uygular.
  • Tip kontrolleri ve anlamlı hata mesajları içerir.
  • typing modülünü kullanarak fonksiyon imzasını tanımlar.

Ayrıca, kullanıcıların doğrudan dosya yolundan belge analizini yapabilmesi için count_words_from_files() adlı yeni bir API fonksiyonu da geliştirilmiştir.

Düzeltilmiş hali:

# --- Internal "Proprietary" Algorithm (Still used, but better encapsulated) ---
# map_function, apply_map, group_function, reduce_function, apply_reduce
# (These are the same as in the "Before" section, so not repeated for brevity,
# but assume they are defined and available)

# --- New Internal Helper Function ---
def filter_function(results, min_occurrences=4):
return {k: v for k, v in results.items() if v >= min_occurrences}

# --- Improved API Functions Exposed to Users ---
from typing import List, Optional, Dict
import warnings

def count_words(corpus: List[str], filter: Optional[int] = None) -> Dict[str, int]:
"""Count all words in a corpus of documents.
:param corpus: A list of strings, where each string
contains the text of a document.
:param filter: int or None. If None, don't filter
the result. Else return words
with at least 'filter' occurrences
in the corpus.
:return: A dictionary of words and their respective
counts, filtered by count as specified.
"""
assert type(corpus) is list, "The corpus to analyse needs to be list of strings"
# Assuming apply_map, group_function, apply_reduce are defined elsewhere
map_results = apply_map(corpus)
group_results = group_function(map_results)
reduce_results = apply_reduce(group_results)
if filter is None:
return reduce_results
else:
assert type(filter) is int, f"The 'filter' argument needs to be a Python int, you specified: '{filter}' which is of type {type(filter)}"
return filter_function(reduce_results, min_occurrences=filter)

def count_words_from_files(files: List[str], skip_corrupted_files: bool = False, filter: Optional[int] = None) -> Dict[str, int]:
"""Count all words in a corpus of documents provided as files
:param files: A list of file names (str) on your local file system.
The files contain the text you want to count words for.
:param skip_corrupted_files: boolean. If True, ignore all files
that can't be read otherwise abort.
:param filter: int or None. If None, don't filter
the result. Else return words
with at least 'filter' occurrences
in the corpus.
:return: A dictionary of words and their respective
counts, filtered by count as specified.
"""
corpus = []
for file_name in files:
try:
with open(file_name, 'r') as f:
text = f.read()
corpus.append(text)
except Exception as e: # More specific exceptions could be caught
msg = f"The file {file_name} cannot be read. Remove it from the corpus or check permissions. Error: {e}"
if skip_corrupted_files:
warnings.warn(msg)
else:
raise ValueError(msg)
return count_words(corpus, filter) # reuse function

Bu fonksiyon:

  • Dosya listesini okur.
  • Hatalı dosyalar varsa kullanıcıyı uyarır veya işlemi durdurur (skip_corrupted_files parametresi).
  • Başarılı dosya içeriklerini count_words() fonksiyonuna aktarır.

Yani bir API geliştirilecekse kullanıcı ihtiyaçlarına uygun, güvenli, belgelenmiş, genişletilebilir olmalıdır.

--

--

Cahit Barkin Ozer
Cahit Barkin Ozer

Written by Cahit Barkin Ozer

Üretken YZ başta olmak üzere teknoloji alanındaki yenilikleri öğrenip sizlerle paylaşıyorum. Youtube Kanalım: https://www.youtube.com/@cbarkinozer

No responses yet