Yapay Zekâ ile Kod Yazarken Sonuca Nasıl Güvenilir?
Yapay zekâ kod üretimini hızlandırabilir; ancak doğru problemi tarif etmek, sınırları belirlemek ve sonucu test etmek geliştiricinin sorumluluğunda kalır. Gerçekçi bir PHP örneği üzerinden güvenilir bir çalışma akışı oluşturalım.
Yapay zekâya bir problemi anlatıp birkaç saniye içinde çalışan bir kod örneği almak artık oldukça kolay. Zor olan ise o kodun bizim problemimizi doğru çözüp çözmediğinden emin olmak.
Kodun hata vermeden çalışması iyi bir başlangıçtır, ancak tek başına yeterli değildir. Yanlış sonucu döndüren bir hesaplama, eksik yetki kontrolü veya beklenmeyen verilerde bozulan bir fonksiyon da ilk bakışta sorunsuz görünebilir.
Bu yazıda, yapay zekâdan destek alırken nasıl daha açık bir görev tanımı hazırlayabileceğimizi ve üretilen kodu küçük bir PHP örneği üzerinden nasıl doğrulayabileceğimizi inceleyeceğiz. Buradaki yaklaşım belirli bir araca bağlı değil; farklı sohbet araçlarında veya kodlama asistanlarında kullanılabilir.
Önce problemi ve sınırlarını tarif edin
“Bana bir sipariş toplamı fonksiyonu yaz” demek hızlı bir başlangıç olabilir. Ancak bu cümle önemli birçok soruyu cevapsız bırakır:
- Tutarlar hangi para biriminde ve hangi formatta tutuluyor?
- Ürün adedi sıfır veya negatif olabilir mi?
- Boş sipariş için sonuç ne olmalı?
- İndirim ve kargo hesaba katılacak mı?
- Geçersiz veri geldiğinde işlem durmalı mı?
Bu soruları modele bırakırsanız boşlukları kendi varsayımlarıyla doldurabilir. Varsayım mantıklı görünse bile mevcut uygulamanızın işleyişine uymayabilir.
Daha açık bir istek şöyle olabilir:
PHP 8.3 için sipariş toplamını hesaplayan saf bir fonksiyon yaz.
Kurallar:
- Ürün fiyatı kuruş cinsinden tam sayı olacak.
- Adet, bir veya daha büyük bir tam sayı olmalı.
- Fiyat negatif olamaz; sıfır olabilir.
- Boş liste için sonuç sıfır olmalı.
- Geçersiz veri ve tam sayı taşması hata üretmeli.
- Vergi, kargo ve indirim bu örneğin dışında.
- Harici paket kullanma.
- Normal ve sınır durumları için PHPUnit testleri öner.
Burada amaç modele uzun bir talimat vermiş olmak değil; kararları mümkün olduğunca açık hâle getirmek. GitHub da istem hazırlarken ilgili bağlamı ve beklentileri belirtmeyi, sonrasında üretilen kodu inceleyip doğrulamayı öneriyor. GitHub Copilot: Prompt engineering
Örnek: Kuruş üzerinden sipariş toplamı
Aşağıdaki fonksiyon, yukarıdaki kurallara göre hazırlanmış küçük bir örnektir. Para birimini veritabanında veya uygulamanın başka bir katmanında nasıl yöneteceğiniz projeye bağlıdır; burada yalnızca kuruş cinsinden tam sayılarla toplama yapıyoruz.
<?php
declare(strict_types=1);
/**
* @param array<int, array{price_cents: int, quantity: int}> $items
*/
function orderTotalInCents(array $items): int
{
$total = 0;
foreach ($items as $item) {
if (
! isset($item['price_cents'], $item['quantity'])
|| ! is_int($item['price_cents'])
|| ! is_int($item['quantity'])
|| $item['price_cents'] < 0
|| $item['quantity'] < 1
) {
throw new InvalidArgumentException('Geçersiz ürün bilgisi.');
}
$price = $item['price_cents'];
$quantity = $item['quantity'];
if (
$price !== 0
&& $quantity > intdiv(PHP_INT_MAX - $total, $price)
) {
throw new OverflowException('Sipariş toplamı çok büyük.');
}
$total += $price * $quantity;
}
return $total;
}
Neden doğrudan float kullanmadık? Ondalıklı sayılar bilgisayarda her değeri tam olarak temsil edemeyebilir. Bu örnekte tutarı kuruş cinsinden tam sayı olarak işleyerek bu hesaplamayı daha açık hâle getiriyoruz.
Bu yaklaşım her ödeme sistemi için tek başına yeterli değildir. İndirim oranları, farklı para birimleri, vergi ve yuvarlama kuralları devreye giriyorsa bunları ayrıca tanımlamak ve test etmek gerekir.
Sadece normal sonucu değil, sınırları da test edin
Yapay zekâ çoğu zaman “normal” senaryoyu örneklendirmekte iyidir. Asıl sorun, beklenmeyen girdilerde ortaya çıkabilir.
Aşağıdaki PHPUnit örneklerinde fonksiyonun OrderTotals.php adlı dosyada, test dosyasıyla aynı klasörde olduğunu varsayıyoruz:
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
require_once __DIR__ . '/OrderTotals.php';
final class OrderTotalsTest extends TestCase
{
public function test_it_calculates_total_in_cents(): void
{
$items = [
['price_cents' => 12500, 'quantity' => 2],
['price_cents' => 3000, 'quantity' => 1],
];
$this->assertSame(28000, orderTotalInCents($items));
}
public function test_empty_order_returns_zero(): void
{
$this->assertSame(0, orderTotalInCents([]));
}
public function test_zero_quantity_is_rejected(): void
{
$this->expectException(InvalidArgumentException::class);
orderTotalInCents([
['price_cents' => 12500, 'quantity' => 0],
]);
}
public function test_integer_overflow_is_rejected(): void
{
$this->expectException(OverflowException::class);
orderTotalInCents([
['price_cents' => PHP_INT_MAX, 'quantity' => 2],
]);
}
}
Projede PHPUnit kuruluysa örnek dosyanın konumuna göre testi şu şekilde çalıştırabilirsiniz:
vendor/bin/phpunit OrderTotalsTest.php
Bu testler, verilen birkaç kuralı doğrular; uygulamanın tamamının hatasız veya güvenli olduğunu kanıtlamaz. Örneğin farklı para birimlerini karıştırmamak veya fiyatın hangi kaynaktan geldiğini doğrulamak bu fonksiyonun sorumluluğu dışında bırakılmıştır.
Yapay zekânın yazdığı testi de inceleyin
Bir asistandan hem kodu hem testleri istemek faydalıdır. Fakat ikisi de aynı yanlış varsayımı benimseyebilir. Örneğin gereksinimlerde adet sıfırdan büyük olmasına rağmen hem fonksiyon hem test sıfır adedi kabul edecek şekilde üretilebilir.
Bu nedenle testleri incelerken kendinize şunları sorun:
- Beklenen sonuç iş kuralından mı geliyor, yoksa sadece fonksiyonun mevcut davranışını mı tekrar ediyor?
- Boş, eksik, yanlış tipte veya sınır değerde veriler denendi mi?
- Başarısız olması gereken durum gerçekten başarısız oluyor mu?
- İlgili işlem veritabanı, yetkilendirme veya başka bir servis içeriyorsa bu katmanlar da uygun şekilde test ediliyor mu?
Özellikle giriş, yetkilendirme ve para işlemleri gibi alanlarda yalnızca aracın ürettiği testlerle yetinmemek gerekir. OWASP’ın yapay zekâ ile güvenli kodlama rehberi, güvenlik açısından kritik senaryoların geliştirici tarafından da ele alınmasını öneriyor.
Önerilen paketi veya komutu çalıştırmadan önce kontrol edin
Asistan bazen var olmayan bir paket adı önerebilir ya da eski bir komutu güncelmiş gibi sunabilir. Paket gerçekten mevcut olsa bile beklenmeyen bağımlılıklar veya projenize uygun olmayan bir lisans içerebilir.
Yeni bir bağımlılık önerildiğinde paket adını resmi kaynağından doğrulamak, sürüm gereksinimlerine ve mevcut projenin bağımlılıklarına bakmak iyi bir alışkanlıktır. Aynı şekilde veritabanını sıfırlayan, dosya silen veya canlı ortama dokunan bir komutu ne yaptığını anlamadan çalıştırmamak gerekir.
Paylaştığınız bağlam da önemlidir. API anahtarlarını, gerçek müşteri verilerini ve üretim ortamına ait gizli dosyaları asistanın görmesine gerek olup olmadığını değerlendirin. Örneği anonimleştirmek çoğu zaman sorunu anlatmak için yeterlidir.
Küçük değişiklikler, daha kolay inceleme
Büyük bir özelliği tek seferde ürettirmek yerine işi adımlara ayırmak incelemeyi kolaylaştırır. Önce mevcut davranışı ve beklenen sonucu açıklayın; ardından küçük bir değişiklik isteyin. Kod farkını okuyun, ilgili testleri çalıştırın ve ancak sonra bir sonraki adıma geçin.
Yapay zekâ bu süreçte alternatifler önerebilir, test senaryoları bulabilir veya anlaşılması zor bir kod parçasını açıklayabilir. Son kararı vermek ve sonucun gereksinimi karşıladığından emin olmak ise geliştiricinin işidir.
İyi bir çalışma akışının amacı yapay zekâya daha az iş yaptırmak değil; ortaya çıkan sonuca neden güvenebildiğinizi bilmektir.