İçeriğe geç
Aralarında Strateji Direktörü, Finans Müdürü, Growth Müdürü ve Backend Mühendisleri'nin de bulunduğu 10'dan fazla pozisyon için ekip arkadaşları arıyoruz • Volt Lines, 3 milyon dolarlık Varlık Teminatlı Şirket Tahvili ihracını tamamladı • Demo talep edin. Ekibinizi daha verimli taşıyın • Volt Lines yakında Birleşik Krallık'ta. Bizimle iletişime geçin • Yazılımımızın Dubai'de her gün yüzlerce köpeğin taşınmasına nasıl yardımcı olduğunu keşfedin • 27-28 Ekim 2026'da Lizbon'da düzenlenecek Fleet Days Europe'ta bizimle buluşun •
Paylaş
Mühendislik 8 dk okuma

Phoenix Projesi: Herkesin yapmayın dediği yeniden yazım

Çalışan bir sistemi sıfırdan yeniden inşa etmek, deneyimli her mühendisin size yapmayın diyeceği tek şeydir ve ekiplerin çoğu için haklıdırlar. Sadece koda bakınca bizim için de haklıydılar. Yine de bu işe girişmemizin sebebi, ulaşmak istediğimiz müşterileri tarif edemeyen bir veri modeliydi.

Phoenix Projesi: Herkesin yapmayın dediği yeniden yazım

Kısıt kodda değil, modeldeydi

Kurumsal çalışanlardan fazlasını taşımak istiyorduk. Okul servisleri, büyük etkinlikler, fabrikalar, evcil hayvan taşımacılığı, acil olmayan hasta taşıma. Farklı ulaşım modelleri, farklı pazarlar ve hiçbirine giremiyorduk.

Her birinin kapsamını çıkardığımızda tahmin aynı şekilde yanlış çıkıyordu. Veri modelimiz tek bir müşteri türünü tanıyordu: hafta içi çalışanları evden sabit bir iş yerine götüren bir şirket.

Bir okul servisi, kendi adına onay veremeyen bir yolcuya bağlı bir veli ister. Bir etkinlik bir cumartesi için kapasite ister, sonraki hafta için hiç istemez. Evcil hayvan taşımacılığı ise uygulamaya hiç giriş yapmayacak bir yolcu ister.

Bunların her biri, aynı tablolardaki farklı bir varsayımı bozuyordu. Yolcu, bir şirketin çalışan listesindeki bir satırdı. Bu yüzden bir işveren olmadan var olamıyor, başkası onun adına onay veremiyor ve bir köpek olamıyordu. Sefer, iki sabit nokta arasında hafta içi tekrarlanan bir işe gidişti. Bu yüzden 400 koltuklu tek bir cumartesi, planlamada bir uç durum değil, bambaşka bir nesneydi. Ödeyen de her zaman işverendi; oysa bu bir veli, bir etkinlik organizatörü ya da bir hastane için geçerli değil. Bunların hepsi için boş bırakılabilir sütunlar ekleyebilirdik. Yapamayacağımız şey, canlı veri eski anlama bağlıyken tabloların anlamını değiştirmekti.

Üzerindeki ekranlar da aynı tek müşteriyi varsayıyordu, dolayısıyla arayüzler de bu işin içine girdi.

Four construction eras stacked in one occupied building: Roman foundation, Byzantine arches, Ottoman stonework, Republic-era apartment.


Sistemimiz, İstanbul'un her yerinde rastlayacağınız türden bir binaydı: Roma temeli, Bizans kemerleri, Osmanlı taş işçiliği, en üstte Cumhuriyet döneminden bir apartman ve içinde hâlâ oturanlar. Şimdi bir de asansör koymayı deneyin. O duvarlardaki her dönemin kendi kuralları var, bu yüzden cevap ya hayır ya da hiçbir şeye dokunmamak şartıyla evet. Tarihi bir yapı için sorun değil. Bizim ise üzerine inşa edebileceğimiz bir temele ihtiyacımız vardı.

Üst katlar tahmin edeceğiniz gibiydi: 2018'de donup kalmış pratikler, yarım bırakılmış iki refaktor ve onlardan kalan iskeleler, test yok, gözlemlenebilirlik yok, tekrar eden kod ve her uygulama için ayrı bir kullanıcı yönetim sistemi. Yangın söndürmek, her sprintte yeni işten daha fazla zaman alıyordu.

Hepsinin altında veri modeli duruyordu ve yanlıştı. Bir temeli refaktorle kurtaramazsınız.

Ekiplerin çoğunun böyle bir sorunu yok. "Asla yeniden yazma" tavsiyesinin iyi olmasının ve Joel Spolsky'nin 2000'de bunun için yaptığı savunmanın hâlâ geçerli olmasının sebebi de bu. Bu tavsiye, kod gözlerine batıyor diye yeniden yazmak isteyen ekipler için. Sizin durumunuz buysa, tavsiye geçerli.

Bu tavsiyeyi bir kenara koyan ilk ekip biz değildik. Dropbox senkronizasyon motorunu sıfırdan yeniden yazdı ve bu kararın başka bir yerde yanlış olacağını açıkça söyledi. Uber, sefer ve arz üzerine kurulmuş bir model yeni dikeyleri taşıyamadığı için fulfillment platformunu yeniden yazdı.

Biz de temeli onarmak yerine değiştirmenin gerekçesini ortaya koyduk. Çünkü yanlış bir şeyi varsayan bir modeli daha güzel bir sürüme doğru refaktor etmek, size yanlış şeyin daha güzel bir sürümünü verir. Kod tabanı, yeniden yazımın neye mal olacağını belirledi. Yapılıp yapılmayacağını belirlemedi.

Kararı dört soru verdi:

  1. Kısıt kodda mı, yoksa kodun temsil ettiği modelde mi? Kodu yerinde refaktor edersiniz. Bir modeli ise canlı veri ona bağlı hale geldikten sonra edemezsiniz. Burada katı olun: "model yanlış", bir ekibin canını sıkan bir kod tabanı hakkında anlatabileceği en hoş hikayedir.
  2. İki sistem, müşterileri tek tek taşıyacak kadar uzun süre yan yana çalışabilir mi? Çalışamazsa geçiş tek seferde olmak zorundadır ve yeniden yazımın şirketleri batıran versiyonu tam olarak budur.
  3. Bitmiş halinin neye benzediğini biliyor muyuz? Tanımı olmayan yeniden yazımlar asla başarısız olmaz, sadece hiç bitmez. Bizim tanımımız: tüm müşteriler yeni çekirdekte, eski çekirdek kapalı, tek bir sistem çalışıyor.
  4. İki sistemi tüm süre boyunca kaldırabilir miyiz ve bu süre ne kadar? Burada bir rakam olmadan, bir geçişi artık sahibi olduğunuz ikinci bir platformdan ayıramazsınız.

Bugün uygulayacağımız beşinci bir test daha var ve o da kimin sorduğuyla ilgili. Nöbet (on-call), hangi arızaların her hafta yaşandığını ve hangi çirkin kodun bir sebebi olduğu için çirkin olduğunu öğretir. Yeniden yazımı savunanlar o çağrı cihazını hiç taşımadıysa, tahminlerinde en pahalıya patlayan parçalar eksiktir. Bu tek başına bizi refaktore geri götürmeye yeter.

Sıfırdan inşa, aşamalı geçiş

Sıfırdan inşa etmek bize dayatılmış bir seçimdi. Strangler fig (boğucu incir) yönteminin ihtiyaç duyduğu ek yeri API yüzeyinden geçer, bizimki ise tablolardan geçiyordu: aynı satırlar eski çekirdek için bir şey, yeni çekirdek için başka bir şey ifade etmek zorundaydı. Bu yüzden çağrıları araya girip yönlendirerek karşıya geçemezdik.

Bu süreci atlatılabilir kılan, geçişin biçimiydi.

Her iki sistemin önünde bir ağ geçidi (gateway) duruyor ve her müşteriyi, onun sahibi olan çekirdeğe yönlendiriyordu. Bir müşteri taşınana kadar eski çekirdek onun için yetkili kaldı ve müşterileri tek tek taşıdık.

Kötü bir günün atlatılabileceği yerden başladık: küçük operasyonlar, sadece hafta içi hizmet ve sabah yedide arayıp konuşabilecek kadar uzun süredir birlikte çalıştığımız bir koordinatör. Bu, işi yavaşa almak değildi; işler ciddiye binmeden önce iki kez yanılma hakkını satın almaktı.

Eski çekirdekle konuşan iki mobil uygulama vardı, biri yolcular, biri sürücüler için ve bir uygulama güncellemesi geçişin parçası olamazdı. Yolcular bizim takvimimize göre güncelleme yapmaz, bazıları hiç yapmaz. Bu yüzden yeni çekirdek, sürümleri ve tuhaflıklarıyla birlikte eski çekirdeğin API'sini konuşmayı öğrendi ve uygulamaların zaten çağırdığı uç noktalardan yanıt verdi. Mühendislerimiz haftalarca, silmekte olduğumuz bir sistemin kalıbında uç noktalar yazdı. Uygulamalar hangi çekirdeğin yanıt verdiğini hiç anlamadı.

A gateway in front of both systems routes each customer to the old core or the new core, and the new core serves the old API versions so the mobile apps keep working.


Her geçiş, o müşterinin koordinatörlerini aynı gün yeni iç platforma taşıdı, böylece veri ve insanlar birlikte taşındı. Geçiş tek yönlüydü. Planlamacılar güzergâhları hangi platformdaysalar orada oluşturuyor, bu yüzden bir geçişi geri almak, canlı bir operasyonu birkaç saat içinde eski sistemde yeniden planlamak demekti. Salı sabahı saat 6'da kimse bunu yapmayacaktı.

Geri dönüş imkânımız yoktu ve bunu baştan biliyorduk. Onun yerine küçük bir etki alanımız, kendi seçtiğimiz bir sıralama ve 47 geçiş boyunca müşterilerin fark ettiği yaklaşık altı olay vardı. Her seferinde ileri gittik, çünkü gidilebilecek tek yön ileriydi.

İlk geçiş yaklaşık iki hafta sürdü ve bize, öncesindeki on bir aylık inşadan daha fazlasını öğretti. Kalan 46'sı dokuz hafta sürdü.

 A bar chart of customers cut over each week: one in the first week then four, eight and five, a peak of eighteen, then a tail of four, one, four and two.


Bunların hiçbiri şans değildi. Mühendislerimiz silmekte olduğumuz bir sistemin kalıbında uç noktalar yazdı, araçlarının değiştiği gün planlamacıların yanında oturdu ve on bir hafta boyunca yük altında ileriye dönük düzeltmeler yaptı. Zirve noktasında bir günde sekiz müşteri taşıdık ve hiçbiri için geri dönüş yolu yoktu.

Yeniden yazımlar inşa aşamasında değil, çoğunlukla geçiş anında ölür.

İki sistemi birlikte çalıştırmak bize neye mal oldu

İki sistem, bir sistemin iki katından daha pahalıya gelir. Bunu dördüncü ayda fark etmek yerine başlamadan önce yazıya döktük.

Her hata düzeltmesi iki kez yapıldı ya da bir kez yapılıp takip edilmesi gereken bir farklılaşma bıraktı. İnşa süresince ikinci bir ortam setini sırtımızda taşıdık. Geçişler boyunca iki canlı sistem çalıştırdık. Bunun maliyeti iki katı değil, tek sistemin yaklaşık %60 fazlasıydı, çünkü yeni çekirdek yerini aldığı sistemden daha yalındı. Güvenlik yüzeyi iki katına çıktı, inceleme yükü de onunla birlikte.

Arayüz tarafı da aynı şekilde ikiye katlandı: iki iç platform, iki web uygulaması, iki görsel dil ve süreç boyunca ikisinde birden çalışan bir operasyon ekibi.

En pahalı kısım hiçbir faturada görünmez. Nöbetçiler iki farklı zihinsel modeli aynı anda taşıdı. O yıl ekibe katılan herkes, silmekte olduğumuz da dahil olmak üzere ikisini de öğrendi.

Bu yüzden süreyi en baştan sınırladık: son müşteri taşınır, eski çekirdek kapanır. On bir ay inşa, ilk geçiş için iki hafta, kalan 46 geçiş için dokuz hafta. Eski çekirdeğin ışıkları sönene kadar toplam on üç ay.

Neyi yanlış yaptık

Sıfırdan yeniden yazımlara yöneltilen klasik eleştiri bizim için de geçerli. On bir ay boyunca yeni sistemin hiç kullanıcısı olmadı ve bir iş akışının yanlış olduğunu bize söyleyecek kimse yoktu.

Yeni veri modeli ayakta kaldı. Etrafındaki bazı şeyler ise kalmadı: planlamacıların beklediği kısayollar, yapmayı hiç düşünmediğimiz özellikler, prensipte doğru ama kullanımda hantal ekranlar. Bunları ilk geçişlerden sonraki haftalarda, hataları da geldikçe düzelterek yayına aldık.

Kapanış

Geçişten bu yana eski çekirdeğin dokunamadığı işleri alıyoruz. Evcil hayvan taşımacılığı ve okul servisleri yayında. Aynı temel, platformun kendisini satmamıza da imkân veriyor ve ilk müşterimiz şimdiden üzerinde. Yazının başındaki listenin geri kalanı artık sadece bir zamanlama meselesi.

Bu bahis pahalıydı ve geri dönüşü zordu. Olumsuz senaryonun bedelini baştan hesapladık, eski sistem kapanana kadar yolumuzdan sapmadık ve sonunda üzerine inşa edebileceğimiz bir temel ile bu işi bir kez başarmış bir ekiple çıktık.

Pek çok ekip büyük bir teknik bahse girer. Çok daha azı sonuna kadar gidip yerini aldıkları sistemi kapatabilir. Yapmak istediğiniz iş buysa, ekibimize katılacak kişileri arıyoruz.

Volt Lines'taki açık pozisyonlar.



Bültene abone ol

Ürün güncellemeleri ve sektör yazıları ayda bir e-postanda.

Çok yakında Takipte kalın