
Sun Aug 16 2026

Hazırsan başlayalım 🚀
Birkaç yıl önce, 10 000 satırlık bir Java monolit ile baş başa kaldım. Kodun yarısı yorum satırıydı, yarısı da “TODO: burayı düzelt” notlarıyla doluydu. Deploy etmek için haftalarca manuel test yapardık, bir hata çıkınca ise “kim yazdı bunu?” diye sorar, cevap gelmezdi.
Geçen sprint’te AI asistanımıza “UserService sınıfını temiz mimariye uygun hale getir” dedik.
Sonuç? Deploy süresi 2 saatten 15 dakikaya düştü ⚡️ ve takım “artık bu kodu korkmadan dokunabiliriz” dedi 😌
Özetle: Legacy modernizasyonu bir macera değil, stratejik bir yatırım olmalı. AI, bu yatırımı daha az riskli, daha hızlı ve öğrenilebilir hale getiren en iyi arkadaşınız.
Hadi bir sonraki bölümde pratik araçlara ve ilk adımlara geçelim! 🚀
Hadi Dürüst Olalım: Her Geliştiricinin Hayali Bu 🎯
Birlikte çalıştığımız legacy sistemlere baktığımızda aklımızdan geçen ilk düşünce şudur: "Bu berbat kod, hadi silip baştan yazalım, her şey düzelecek." Kulağa çok cazip geliyor, değil mi? Yeni bir mimari, temiz kod, hiçbir technical debt yok... Mükemmel bir dünya.
Ama gerçek hayat o kadar da masal gibi geçmiyor. Ben de bir zamanlar bu tuzağa düştüm, belki siz de düştünüz. Hadi neden "big rewrite" stratejisi neredeyse her zaman faciaya döner, onu beraber çözelim.
1. Zaman ve Bütçe: Her Zaman Tahmininizin Katı Olur 📉
2. İş Sürekliliği: Müşteriniz Durmuyor 🛑
3. Bilgi Kaybı: "Neden Böyle?" Sorusunun Cevabı Kayboldu 🧠
// Eski kodda bu satır var:
if (user.status === 'PENDING' && order.amount > 1000) {
// TODO: Bu kontrol neden var? Kimse bilmiyor.
requireManualApproval();
}
4. İkinci Sistem Etkisi (Second System Effect) 🏗 Fred Brooks'un The Mythical Man-Month kitabından: "Bir mimarın yaptığı ikinci sistem, hayalindeki en tehlikeli sistemdir; ona her özellikleri eklemek ister."
Netscape 6.0 Hikayesi (1998-2000)
Daha Yakın Bir Örnek: Basecamp (eski 37signals)
Burada heyecanlandırmak için değil, gerçekçi bir bakış açısı için söylüyorum:
| AI Yetenekleri | Rewrite Riskini Nasıl Azaltır? |
|---|---|
| Kod Anlama / Dökümantasyon | Legacy kodu okuyup, business rule'ları çıkarıyor, "neden böyle?" sorusuna cevap veriyor |
| Refactoring Asistanı | "Baştan yaz" yerine, parça parça güvenli refactoring öneriyor, testler yazıyor |
| Strangler Fig Pattern Uygulaması | Eski sistemin etrafını saran yeni modülleri planlı bir şekilde çıkarmanıza yardımcı oluyor |
| Test Generasyonu | Eski sistemin davranışını kilitleyen characterization testleri dakikalar içinde üretiyor |
Önemli Not: AI sihirli bir değnek değil. Ama "baştan yaz" kararı vermeden önce, legacy sistemin ne yaptığını gerçekten anladığınızdan emin olmanızı sağlıyor. Ve bu, rewrite tuzağının en büyük nedenidir: Sistemi anlamadan yeniden yazmaya çalışmak.
Beni hatırlatır mısınız? En iyi rewrite, yapılmayan rewrite'dir. Veya en azından, "baştan yaz" diye başlayıp "parça parça değiştir" diye bitiren o projedir. 😉
Hazırsan bir sonraki bölümde "Strangler Fig Pattern'i pratikte nasıl uygularız?" konusuna geçebiliriz. Veya sizin yaşadığınız rewrite hikayeleri var mı? Yorumlarda paylaşalım! 👇
Hazırsan başlayalım 🎯. Strangler Fig, eski monolitik uygulamayı kademeli olarak yeni mikro servislerle değiştirmenin pratik bir yoludur. Fikir basit: yeni işlevselliği yanına ekle, trafiği yönlendir, eski kodu yavaş yavaş sil.
| Aşama | Ne Yapılır? | Kontrol Noktası |
|---|---|---|
| Shadow | Yeni servise kopyalı trafik gönder, yanıtı karşılaştır | Hata oranı < %0.1 |
| Canary | Gerçek trafiğin %5‑%10'u yeni servise | SLA, latency, hata oranı hedeflerde |
| Full Cutover | Tüm trafik yeni servise, eski endpoint deprecated | Monitoring 24‑48 s stabil |
| Decommission | Eski kod ve veritabanı tabloları temizlenir | Backup doğrulandı, rollback planı hazır |
# kong.yml – basit Strangler Fig routing örneği
_format_version: "3.0"
services:
- name: legacy-order-service
url: http://legacy-orders:8080
routes:
- name: legacy-orders-route
paths:
- /orders
strip_path: false
plugins:
- name: correlation-id # tracing için
- name: new-order-service
url: http://new-orders:8080
routes:
- name: new-orders-route
paths:
- /orders/v2
strip_path: false
plugins:
- name: correlation-id
# Canary: %10 trafiği v2'ye yönlendir
plugins:
- name: rate-limiting
config:
minute: 1000
policy: local
- name: request-transformer
config:
add:
headers:
- "x-canary:true"
route: new-orders-route
protocols:
- http
# Kong'un `canary` eklentisi veya custom Lua ile %10 trafik yönlendirilebilir
Ne oluyor burada?
/orders → eski servise gider./orders/v2 → yeni servise gider.request-transformer ile canary header eklenir; downstream servisler bu header’a göre davranabilir.Bu yöntemle risk 최소화 edilir, deployment her gün daha küçük hale gelir ve ekip sürekli değer üretir. 🚀
Karakterizasyon testi (characterization test), legacy kodun şu anki davranışını belgelemek için yazılır.
Birim testten farkı şudur:
Özet: Karakterizasyon testi = “Mevcut davranışın fotoğrafı” 📸
// @workspace
// Aşağıdaki fonksiyon için Jest karakterizasyon testleri yaz.
// - Tüm girdi kombinasyonlarını (normal, edge, hata) kapsasın.
// - Mevcut davranışı değiştirme, sadece gözlemle.
// - Test isimleri “should …” formatında olsun.
İpucu: Prompt’a “sadece mevcut davranışı test et, refactor yapma” eklemek AI’ı gereksiz yeniden yazım'dan kaçınmaya zorlar.
// src/legacy/priceCalculator.ts
export function calculatePrice(base: number, discount?: number, taxRate = 0.18): number {
if (base < 0) throw new Error('Base price cannot be negative');
const disc = discount ?? 0;
const priceAfterDiscount = base * (1 - disc);
return priceAfterDiscount * (1 + taxRate);
}
// tests/priceCalculator.characterization.test.ts
import { calculatePrice } from '../../src/legacy/priceCalculator';
describe('calculatePrice – characterization tests', () => {
// Normal akış
test('should return price with default tax when no discount', () => {
expect(calculatePrice(100)).toBeCloseTo(118); // 100 * 1.18
});
test('should apply discount then tax', () => {
expect(calculatePrice(200, 0.1)).toBeCloseTo(212.4); // 200*0.9*1.18
});
// Edge case: discount = 0
test('should behave same as no discount when discount is 0', () => {
expect(calculatePrice(150, 0)).toBeCloseTo(177);
});
// Edge case: discount = 1 (free)
test('should return only tax when discount is 1', () => {
expect(calculatePrice(100, 1)).toBeCloseTo(0); // 0 * 1.18 = 0
});
// Hata durumu
test('should throw when base price is negative', () => {
expect(() => calculatePrice(-10)).toThrow('Base price cannot be negative');
});
});
Çalıştırma komutu
npx jest tests/priceCalculator.characterization.test.ts --verbose
Bu sayede ne oluyor?
- Mevcut
calculatePricedavranışı testlerle kilitlenir.- Gelecekte refactor yaparsanız (ör. vergi oranını parametreye taşıma) testler anında kırmızı yanar ⛔.
- AI ile dakikalar içinde onlarca test elde ettik, manuel yazmak yerine doğrulama odaklandık ✅.
Karakterizasyon testleri legacy kodu güvenle değiştirmenin ilk adımıdır.
AI asistanı doğru prompt ile mevcut davranışı saniyeler içinde test koda dönüştürür; siz sadece “bu testler geçiyor mu?” diye kontrol edersiniz.
Böylece bilinmeyen davranış belgeye dönüşür ve gelecekteki her değişiklik güvenli bir ağ üzerine oturur 🎯.
Eski bir projeye atıldığında hissettigin o "nereden başlayayım?" paniği biliyorsun ya 😅 Dokümantasyon yok, yazan kişi ayrıldı, ve kod içinde gizli bağımlılıklar (veritabanı şemaları, harici API'ler, global state) saklı duruyor. İşte bu "kara kutuyu" açmak için AI harika bir lanterna olabilir 🔦
HttpClient wrapper'ları, base URL'ler config dosyalarında, retry logic'i bir yerde timeout ayarı başka yerdeBunları manuel bulmak günlerinizi alır. AI ise kod taraması → özetleme → çağrı grafiği çıkarma zincirini dakikalar içinde yapabilir ⚡
Cursor açıksa, Cmd+L (veya Ctrl+L) ile Chat panelini aç ve Codebase modunu seç. Sonra şu soruları sorabilirsin:
"Bu projedeki tüm veritabanı bağlantı noktalarını ve hangi tabloların kullanıldığını listele"
"
PaymentServicesınıfı hangi harici API'leri çağırıyor? Base URL'ler nerede tanımlı?"
"Global state olarak kullanılan tüm singleton/static sınıfları bul"
Cursor embedding'ler üzerinden ilgili dosyaları çeker, context'e koyar ve cevap verir. Ama dikkat: bazen hallucination yapar ❗️ Cevabı aldıktan sonra "Bu dosyadaki satır X-Y aralığını göster" diyerek doğrula.
Cursor yoksa veya veri dışarı çıkmamalıysa, Ollama ile lokal model koşturup kendi bash pipeline'ını yazarsın. Şu basit script bir başlangıç olabilir 👇
#!/usr/bin/env bash
# scan_and_ask.sh — Projeyi tara, özetle, soru sor
# Kullanım: ./scan_and_ask.sh "Sorunuz buraya"
set -euo pipefail
QUESTION="${1:-Projedeki ana bağımlılıkları ve veri akışını özetle}"
PROJECT_ROOT="${2:-.}"
MODEL="${3:-codellama:13b}" # ollama pull codellama:13b yapmayı unutma
OUTFILE="ai_analysis_$(date +%Y%m%d_%H%M%S).md"
echo "🔍 Proje taranıyor: $PROJECT_ROOT"
# 1. Sadece ilgili dosyaları topla (node_modules, .git, build artifact'leri atla)
mapfile -t FILES < <(find "$PROJECT_ROOT" -type f \
\( -name "*.cs" -o -name "*.java" -o -name "*.py" -o -name "*.js" -o -name "*.ts" -o -name "*.go" -o -name "*.php" \) \
! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/bin/*" ! -path "*/obj/*" ! -path "*/build/*" ! -path "*/dist/*" \
| head -200) # context window'ı aşmamak için limit
echo "📄 ${#FILES[@]} dosya bulundu, modele gönderiliyor..."
# 2. Dosyaları tek bir context'e birleştir (basit versiyon)
CONTEXT=""
for f in "${FILES[@]}"; do
CONTEXT+="\n=== DOSYA: $f ===\n"
CONTEXT+="$(cat "$f")\n"
done
# 3. Prompt'u hazırla
PROMPT=$(cat <<EOF
Sen bir senior software architect'sın. Aşağıdaki kod tabanını analiz et ve şu soruyu cevapla:
SORU: $QUESTION
KOD TABANI:
$CONTEXT
Cevap formatı:
- **Özet**: 3-5 cümlelik genel bakış
- **Bulunan Bağımlılıklar**: Madde madde (veritabanı, API, global state, vb.)
- **Riskli Alanlar**: Refactoring zorlukları, tight coupling noktaları
- **Öneriler**: Adım adım yapılması gerekenler
EOF
)
# 4. Modeli çağır (streaming olmasa da olur, sadece sonuç lazım)
echo "$PROMPT" | ollama run "$MODEL" > "$OUTFILE"
echo "✅ Analiz tamamlandı: $OUTFILE"
echo "📖 İçeriği görmek için: cat $OUTFILE"
Nasıl çalışıyor? 🤔
find ile projedeki kod dosyalarını toplar (binary/config dosyalarını atlar)=== DOSYA: path === başlığıyla birleştirir → model hangi dosyadan geldiğini bilsinollama run ile lokal modele gönderir, cevabı Markdown dosyasına yazar💡 İpucu: Context window'ı dolarsa
head -200limitini artır/azalt, veya dosyaları önce özetletip (map-reduce) sonra soru sor. Basit birsummarize.shyazıp her dosya için 3-5 satırlık özet alıp onları birleştirmek daha akıllıca olur 🧠
| Manuel Yöntem | AI Pipeline |
|---|---|
| Haftalarca kod okuma | Dakikalar içinde harita 🗺 |
| Kaçırılan bağımlılıklar | Sistematik tarama ile yakalama |
| Bilgi silolara hapsolur | Paylaşılabilir Markdown raporu |
| Yeni ekip üyesi onboarding'i zor | "Bu scripti çalıştır, raporu oku" 🚀 |
AI harika bir keşif aracı, ama kesin kaynak değil. Çıktıyı aldında:
PaymentService.cs satır 142'de mi?"dotnet-depend / pydeps / madge gibi araçlarla görselleştirHazırsan bir sonraki adımda bu haritayı kullanarak nasıl güvenli refactoring yaparız ona bakalım 👇
Hazırsan başlayalım 🚀. AI ile refaktör yaparken büyük atlamalar yerine baby steps (küçük adımlar) prensibini takip etmek, testlerin yeşil kalmasını ve code review sürecinin hızlanmasını sağlar. İşte nasıl uyguladığım:
“Bu
CalculateDiscountmetodunu, CalculateBasePrice ve ApplyDiscount olarak iki metoda ayır. Her biri tek bir iş yapmalı.”
“
calcmetodunuCalculateTotalPriceolarak yeniden adlandır, parametre isimlerini deunitPrice,quantityyap.”
“
OrderService.PlaceOrder(customerId, productId, quantity, shippingAddress, billingAddress)imzasınıOrderRequestDTO’su ile değiştir.”
Aşağıda eski hali ve Copilot önerisiyle refaktörlenmiş hali diff formatında görebilirsin. Değişiklikler tek tek uygulandı, her adımda testler yeşil kaldı.
- public decimal CalculateDiscount(decimal price, int quantity, bool isVip, string couponCode)
- {
- decimal basePrice = price * quantity;
- decimal discount = 0;
-
- if (isVip)
- discount += basePrice * 0.10m;
-
- if (!string.IsNullOrEmpty(couponCode))
- discount += basePrice * 0.05m;
-
- return basePrice - discount;
- }
+ // 1️⃣ Extract Method: Base price hesaplama ayrıldı
+ private decimal CalculateBasePrice(decimal price, int quantity)
+ => price * quantity;
+
+ // 2️⃣ Extract Method: İndirim mantığı ayrıldı
+ private decimal CalculateDiscount(decimal basePrice, bool isVip, string couponCode)
+ {
+ decimal discount = 0;
+
+ if (isVip)
+ discount += basePrice * 0.10m;
+
+ if (!string.IsNullOrEmpty(couponCode))
+ discount += basePrice * 0.05m;
+
+ return discount;
+ }
+
+ // 3️⃣ Public API: Parametre objekti ile temizlendi
+ public decimal CalculateFinalPrice(OrderRequest request)
+ {
+ var basePrice = CalculateBasePrice(request.UnitPrice, request.Quantity);
+ var discount = CalculateDiscount(basePrice, request.IsVip, request.CouponCode);
+ return basePrice - discount;
+ }
+
+ // 4️⃣ Introduce Parameter Object
+ public record OrderRequest(
+ decimal UnitPrice,
+ int Quantity,
+ bool IsVip,
+ string CouponCode
+ );
Ne oldu?
CalculateFinalPrice ve OrderRequest isimleri domain’e uygun hale geldi.record altında toplandı, gelecekte yeni alan eklemek breaking change yaratmıyor.| Adım | Test Sonucu | Review Süresi |
|---|---|---|
| Extract Method | 🟢 Yeşil | -30 % |
| Rename | 🟢 Yeşil | -20 % |
| Parameter Object | 🟢 Yeşil | -25 % |
Küçük adımlarla gittiğimizde her commit tek bir mantıksal değişiklik içerir, bu da reviewer’ın odaklanmasını kolaylaştırır 🎯.
Özet: AI’yi “büyük refaktör” motoru değil, asistan gibi kullan. Her seferinde bir refaktör türü (Extract, Rename, Parameter Object) iste, testleri çalıştır, commit at. Böylece güvenli, izlenebilir ve hızlı bir refaktör süreci yaşarsın 🚀.
Hadi başlayalım! 🤖 Kısa bir süre önce AI tarafından yazılan ve bir PR'ye eklemiş bir kartı hayal et. İyi fikir, değil mi? Ancak iş production'a gelince, garantilere ihtiyacımız var. 🚀 İşte tam burada CI/CD, statik analiz, mutasyon testi, canary dağıtımı ve feature flag'ler devreye giriyor.
Aşağıda, bir AI tarafından üretilen commit'de her dosya değişikliği yapıldığında çalışan, okunabilir ve modüler bir GitHub Actions akışını görebilirsiniz. Bunu kopyalayıp kendi repository'nize yapıştırın, .github/workflows/ai-checks.yml olarak kaydedin ve geri kalanını otomatik hale getirin.
name: AI Kodu Kontrol Et
# 🍃 Her branch'te ve PR'de çalış
on:
push:
branches: [ main, develop ]
pull_request:
types: [ opened, synchronize, reopened ]
jobs:
static-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Node projesi ayarla
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Eslint ile statik analiz
run: npm run lint
- name: Prettier ile kod biçimlendirme kontrolü
run: npm run format:check
unit-and-mutation:
needs: static-analysis # 🛑 analiz başarısız olursa ileri gitme
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Node projesi ayarla
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Unit test'leri çalıştır
run: npm test
- name: Mutasyon testlerini çalıştır
run: npm run mutate
continue-on-error: true # ⛔ mutasyon başarısız olsa bile dağıtım devam edebilir
canary-deploy:
needs: unit-and-mutation
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop' # 🎯 yalnızca develop branch'inde canary yap
steps:
- uses: actions/checkout@v4
- name: Canary ısıtasını tetikle (örnek)
id: canary
run: |
echo "::set-output name=url::https://canary.yourapp.com"
echo "::set-output name=flag::ai-feature-enabled"
- name: Feature flag'yi etkinleştir
run: |
# Örnek: LaunchDarkly CLI kullanarak flag'yi etkinleştir
ld-cli features:toggle --project prod --feature ${{ steps.canary.outputs.flag }} --target canary
rollback-if-needed:
needs: canary-deploy
runs-on: ubuntu-latest
if: failure() && github.ref == 'refs/heads/develop'
steps:
- name: Canary'yi otomatik olarak geri al
run: |
echo "⚠️ Canary başarısız oldu, üretimdeki flag'yi kapat"
# Örnek: LaunchDarkly CLI kullanarak flag'yi kapat
ld-cli features:toggle --project prod --feature ${{ env.CANARY_FLAG }} --target production --off
Bu sayede ne oluyor?
develop branch'inde çalışır ve bir feature flag'i etkinleştirir. Her şey bozulduğunda, bir sonraki commit'te otomatik olarak geri alırız.git revert veya container registry'den önceki etiket ile geri alırız.Bunlar sadece birkaç basit adım. Bunları deploy pipeline'ına ekleyerek AI tarafından üretilen kodun güvenle production'a gitmesini sağlayabiliriz. 🛡️
Devam et! Bunu repository'nize ekleyin, AI ile geliştirme yapın ve pipeline'ın sizi koruduğunu bilin. Daha güvenli bir kodlama süreci dilerim! 🚀
Hazırsan başlayalım 🚀
Küçük bir e‑ticaret monolith’inden Sipariş Servisini ayırıp Strangler Fig desenini uyguluyoruz. Süreç üç ana adımdan oluşuyor: karakterizasyon testi, yeni servis iskeleti ve API Gateway yönlendirmesi. Her adımda hangi AI aracının (Copilot, Cursor, lokal model) ne yaptığını da not alacağız.
Önce mevcut OrderController davranışını kilitlememiz lazım. Copilot’a “Express route için Jest + Supertest karakterizasyon testi yaz” dedik ve şu çıktıyı aldık:
// tests/orderCharacterization.test.js
const request = require('supertest');
const app = require('../src/app'); // monolith entry point
const Order = require('../src/models/Order');
describe('OrderService – karakterizasyon testleri', () => {
beforeAll(async () => {
// Test veritabanını temizle ve seed data ekle
await Order.deleteMany({});
await Order.create({ _id: '507f1f77bcf86cd799439011', userId: 'u1', total: 100, status: 'CREATED' });
});
it('GET /orders/:id → 200 ve doğru sipariş döner', async () => {
const res = await request(app).get('/orders/507f1f77bcf86cd799439011');
expect(res.status).toBe(200);
expect(res.body.total).toBe(100);
expect(res.body.status).toBe('CREATED');
});
it('POST /orders → 201 ve sipariş oluşturur', async () => {
const payload = { userId: 'u2', items: [{ productId: 'p1', qty: 2, price: 50 }] };
const res = await request(app).post('/orders').send(payload);
expect(res.status).toBe(201);
expect(res.body.total).toBe(100);
expect(res.body.status).toBe('CREATED');
});
});
Ne oldu?
Testler yeşil çıkınca OrderService’i ayrı bir repo’ya taşıma vakti. Cursor’da “Node.js/Express micro‑service scaffold with Docker” promptunu verdik. İki dosya çıktı:
package.json
{
"name": "order-service",
"version": "1.0.0",
"description": "Sipariş mikro‑servisi",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"test": "jest --coverage"
},
"dependencies": {
"express": "^4.19.2",
"mongoose": "^8.5.0",
"dotenv": "^16.4.5"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^7.0.0",
"nodemon": "^3.1.4"
}
}
Dockerfile
# ---- Build stage ----
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# ---- Runtime stage ----
FROM node:20-alpine
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "src/index.js"]
Cursor’un katkısı
npm ci ile deterministik bağımlılık kurulumu sağlandı.devDependencies test stage’inde kalacak, production imajı küçük kaldı ✅.Monolith’teki /orders trafiğini yeni servise yönlendirmek için NGINX (veya Kong/Envoy) konfigürasyonuna bir route eklememiz gerekiyordu. Lokal model’e “NGINX upstream order-service 3000 portuna proxy_pass kuralı yaz” dedik ve şu snippet’i elde ettik:
# /etc/nginx/conf.d/upstream-order.conf
upstream order_service {
server order-service:3000; # docker‑compose service adı
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
location /orders/ {
proxy_pass http://order_service/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
}
}
Lokal model ne yaptı?
keepalive ve Connection "" ile HTTP/1.1 keep‑alive performans artışı sağlandı ⚡.| Adım | Araç | Üretilen Çıktı | Not |
|---|---|---|---|
| Karakterizasyon testi | GitHub Copilot | orderCharacterization.test.js |
Mevcut kodu okuyup test iskeleti çıkardı |
| Servis iskeleti (package.json + Dockerfile) | Cursor | package.json, Dockerfile |
Multi‑stage build, production‑ready |
| API Gateway kuralı | Lokal Model (CodeLlama via Ollama) | upstream-order.conf |
Docker DNS + keep‑alive optimizasyonu |
Sonuç:
Testler yeşil, Docker imajı build ediliyor, Gateway yönlendirme hazır. Artık Strangler Fig ile monolith’ten OrderService’i parça parça çekebilir, canary dağıtım yapabilir ve güvenle mikroservis yolunda ilerleyebiliriz 🚀.
Bir sonraki yazıda canary stratejisi ve observability (metrics, tracing) üzerine konuşacağız. Görüşmek üzere! 👋
Teknik araçlar tek başına yeterli değil. Alışkanlıkları değiştirmeden gerçek bir modernizasyon olmuyor. Benim deneyimimde şu dört ritüel takım kültürünü kökten sallıyor 🎯:
prompts/ klasörü tutuyoruz. Herkes en sık kullandığı, işe yarayan prompt’ları (ör. “Refactor this legacy Java class to Spring Boot 3”, “Generate unit tests for this REST endpoint”) buraya commit atıyor. Böylece “tekrar icat etme” yok oluyor.prompts/ reposunu oluştur ve ilk 3 prompt’u commit at – Örn. “Generate JUnit 5 tests for Spring service”, “Explain this legacy COBOL paragraph”, “Suggest modern Dockerfile for this Java app”.Bu küçük adımlar birikince, takım “AI’yi birer araç olarak değil, günlük bir alışkanlık olarak kullanmaya başlar. Ve o an modernizasyon artık bir proje değil, kültür haline gelir 🚀.
Legacy modernizasyonu bir süreçtir 🎯
AI bu yolda navigatördür 🤖
Sürücü sizsiniz 🚗
İlk küçük adımı bugün atın ✨
Geleceğinizde daha temiz, daha hızlı ve daha güvenilir bir kod bazı sizi bekliyor.
Hadi birlikte bu maratona başlayalım! 🏁
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved