<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Yazılım Davranışlarının Dinamik Olarak Değiştirilebilmesini Sağlayan Yeni Bir Yaklaşım</article-title>
      </title-group>
      <contrib-group>
        <aff id="aff0">
          <label>0</label>
          <institution>TOBB Ekonomi ve Teknoloji Üniversitesi</institution>
          ,
          <addr-line>Ankara</addr-line>
          ,
          <country>Türkiye Web Page:</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2017</year>
      </pub-date>
      <volume>37</volume>
      <issue>3</issue>
      <abstract>
        <p>Özet. Günümüzde web ve mobil platformlar üzerinden sağlanan yazılımlar sık sık güncellenebilmektedir. Güncellemeler ile beraber yazılımların davranışları değişir. Bazı davranışlar istenmeyen hasarlara yol açabilir. Bu sebeple müşteriye ulaşan hatalı davranışların düzeltilmesi yeni güncellemeler yoluyla yapılmaktadır. Kaynak kodlarda düzeltmelerin yapılması, değişikliklerin test edilmesi ve kaynak kod denetimlerinden geçmesi, bu değişikliklerle yeni yazılım versiyonunun inşa edilmesi ve güncellenmiş versiyonun üretim ortamlarına konuşlandırılması saatler alabilir. Dolayısıyla birçok müşteriyi etkileyebilecek ve hatalı olduğunda müşterilerde büyük iş kayıplarına yolaçabilecek değişikliklerin saniyeler mertebesinde düzeltilebilmesi yazılım üreticilerinin prestijinin korunması ve müşteri memnuniyetinin devamı için önemli bir ihtiyaçtır. Bu çalışmada koşan yazılımların davranışlarını dinamik olarak değiştirilebilmesini sağlayacak bir yaklaşım ve bu yaklaşımı gerçekleştiren bir yazılım aracı sunmaktayız. Yaklaşımımız yazılım güncellemelerinin herhangi bir kod değişikliği gerektirmeden kademeli olarak devreye alınmasını veya saniyeler içerisinde tamamen devreden çıkarılmasını sağlamaktadır. Aynı zamanda yaklaşımımız deneysel sayılabilecek yeni yazılım özelliklerinin üretim ortamında ufak bir kullanıcı kitlesi üzerinde denenebilmesini mümkün kılmaktadır. Anahtar Kelimeler: Yazılım güncellemesi, Yazılımların davranışlarının dinamik olarak değişitirilmesi, Yazılım konuşlandırması, Dönemeç</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>Çağdaş Evren Gerede
TOBB University of Economics and Technology, Ankara, Turkey</p>
      <p>Web Sayfası: http://cegerede.etu.edu.tr</p>
    </sec>
    <sec id="sec-2">
      <title>Giriş</title>
      <p>
        Günümüzde İnternet alt yapısının giderek iyileşmesi ile beraber web ve
mobil platformlar üzerinden sunulan yazılımlar elektronik olarak sık sık
güncellenebilmektedir[
        <xref ref-type="bibr" rid="ref1 ref2">1, 2</xref>
        ]. Firmaların web uygulamalarını haftada birkaç defa
güncelleyerek üretim ortamlarındaki sunucularına aktarmaları standart hale gelmiştir.
Mobil uygulamalar için App Store ve Google Play gibi uygulama dükkanlarının
onay süreçleri güncelleme sürecini uzatsa da firmaların iki-üç haftada bir yeni
güncellemeler yapabildiğini görmekteyiz[3]. Yazılım güncellemelerini genel olarak
yeni özelliklerin eklenmesi, hataların düzeltilmesi, ve kaynak kodun bakımının
kolaylaştırılması için iyileştirilmesi olarak guruplayabiliriz. Son kategori yazılımın
davranışını aynı tutma amacı güder. İlk iki kategorideki güncellemeler ile
beraber ise yazılımların davranışları kasıtlı olarak değiştirilir. Bu değişikliklerin
bazılarında istenmeden hatalar yapılmış olabilir ve de bunlar yazılımın bazı
fonksiyonlarının yanlış çalışmasına yol açabilir.
      </p>
      <p>Müşteriye ulaşan hatalı davranışların düzeltilmesi genellikle yeni güncellemeler
yoluyla yapılmaktadır. Kaynak kodlarda gerekli düzeltmelerin yapılması,
değişikliklerin test edilmesi ve diğer geliştiriciler tarafından yapılan kaynak kod
denetimlerinden geçmesi, bu değişikliklerle yeni yazılım versiyonunun inşa edilmesi
ve güncellenmiş versiyonun üretim ortamlarına konuşlandırılması saatler
alabilir[4]. Dolayısıyla birçok müşteriyi etkileyebilecek ve hatalı olduğunda
müşterilerde büyük iş kayıplarına yolaçabilecek değişikliklerin saniyeler içerisinde
düzeltilebilmesi yazılım üreticileri için önemli bir ihtiyaçtır. Çünkü aksi halde
müşterinin hem üreticiye karşı güveni sarsılacak hem de ürün ile ilgili
memnuniyeti olumsuz olarak etkilenecektir[5].</p>
      <p>Üreticiler bu tür sorunlarla karşılaşmamak için geleneksel olarak kullanıcı
trafiğinin en aza indiği saatlerde güncellemelerini üretim ortamlarına
konuşlandırmayı tercih etmektedir. Böylece eğer güncellemelerde bir sorun ortaya
çıkarsa en az sayıda kullanıcı bu durumdan etkilenecektir. Fakat bu
geleneksel yaklaşımın önemli problemleri vardır. Birincisi, örneğin, bir Cumartesi günü
sabaha karşı saat 3:00’da çalışıyor olmak çalışanların iş memnuniyetlerini
olumsuz olarak etkiler. İkincisi, kullanıcı trafiğinin azaldığı saatlerde güncellemelerin
etkilerini yeterli oranda görmek mümkün olmamaktadır. Örneğin yalnızca gün
içerisinde kullanılmakta olan bir özelliğin güncellemeden etkilenip etkilenmediğini
test edebilmek mümkün değildir. Dolayısıyla ilerleyen saatlerde kullanıcı trafiğinin
artmasıyla beraber birçok sorun gün yüzüne çıkabilir. Güncellemelerin
yapılmasından sonra uzun bir zaman geçtiği için sorunlara müdahale edebilecek ekipler
çoktan evlerine dağılmış olabilir. Bu yaklaşımın üçüncü problemi ise birçok farklı
coğrafyada kullanılan yazılımlar için kullanıcı trafiğinin azaldığı bir zaman
aralığının mevcut olmamasıdır. Bir bölgenin mesai sonrası zamanı bir başka
bölgenin mesai saatleriyle çakışabilir. Bu durumlarda da bu yaklaşımı kullanmak
mümkün değildir.</p>
      <p>Bu çalışmada koşan yazılımların davranışlarının dinamik olarak yönetilmesini
sağlayacak bir yaklaşım önermekteyiz. Yaklaşımımız “bilgi saklama” (İng.
information hiding) ve “korunmuş varyasyonlar” (İng. protected variations)
prensipleri ile uyumludur[6, 7]. Bu yaklaşım sayesinde günün herhangi bir saatinde
sunucular üzerinde güncellemeler yapılabilir ve bu güncellemeler kullanıcıların
karşısına kademeli olarak çıkartılabilir. Böylece kullanıcıların hangi yeni
davranışlardan etkilenebileceği kontrol edilebilecek ve gerektiğinde güncellemeler devreden
çıkartılabilecektir.</p>
      <p>Yaklaşımımız herhangi bir yazılım kaynak kodu güncellemesi gerektirmez.
Dolayısıyla davranışlar yukarıda bahsettiğimiz uzun sürecek geliştirme-test
etmeinşa etme-konuşlandırma sürecinden bağımsız olarak değiştirilebilir. Aynı
zamanda yaklaşımımız deneysel sayılabilecek yeni yazılım özelliklerinin üretim
ortamında ufak bir kullanıcı kitlesi üzerinde denenebilmesini mümkün
kılmaktadır. Böylece yeni bir fikir tüm kullanıcıları olumsuz olarak etkilemeden ama
aynı zamanda da kullanıcıların bir alt kümesinden geribildirimler alınarak
olgunlaştırılabilir.
2</p>
    </sec>
    <sec id="sec-3">
      <title>Yaklaşım</title>
      <p>Yaklaşımımızda kaynak kod içerisinde eski ve güncellenmiş kod bölgeleri aynı
anda bulundurulur. Bir istek için hangi kaynak kod bölgesinin çalıştırılacağı
dönemeç (İng. junction) diye tanımladığımız değişken değerlerine bakılarak çalışma
zamanınında dinamik olarak belirlenir. Dönemeçlerin değerleri yazılımın dışında
bir başka sistem içerisinde saklanır. Bu sistem üzerinden dönemeç değerleri
güncellenebilir. Uygulama ise periyodik olarak yeni dönemeç değerlerini indirir. Bu
sayede yazılımın davranışları dinamik olarak değişmiş olur.</p>
      <p>Tablo 1’de örnek dönemeç kullanımları gösterilmektedir. Örneğin, bir loglama
fonksiyonu çağrıldığında log mesajının yeni sisteme mi yoksa var olan sisteme mi
kaydedileceğine bir if-else bloğu ile karar verilmektedir. Karar şartının değeri bir
fonksiyon çağrılarak elde edilir. Örnekte bool fonksiyon ismi dönemecin boolean
veri tipinde olduğunu işaret eder. “LOG_TO_NEW_SYSTEM” kullanılan
dönemecin ismini içeren String tipinde bir sabit değişkendir. Fonksiyonun ikinci
parametresi verilen isimde bir dönemeç bulunamadığında dönecek varsayılan
değeri gösterir. Dönemeç kütüphanesinin fonksiyonları “d” değişkeni tarafından
sağlanır. Dolayısıyla, satır 3’e göre o an dönemeç değeri “true” ise mesaj yeni
sisteme loglanır. Aksi halde varolan sistem kullanılmaya devam eder.</p>
      <p>Yine Tablo 1’de ikinci satırda bir özelliğin yalnızca bir grup kullanıcıya
kademeli olarak sağlanmasına örnek gösterilmiştir. Burada “fraction” tipinde bir
veri kullanılmıştır. Dönemeç tanımlanmadığında ekran arayüzü oluşturulurken
deneysel olarak eklenmiş yeni bir diyalog penceresi gösterilmemektedir çünkü
dönemecin varsayılan değeri sıfırdır ve çalışma zamanında karar şartının sol
tarafında sıfır ile bir arasında rastgele bir sayı seçilir. Bu sayı hiçbir zaman
sıfırın altında olmayacağı için uygulama birinci if-bloğu içerisine giremez.
Dönemeç değeri 0:10 olarak güncellendiğinde ise kullanıcı trafiğinin rastgele %10’u
için karar şartı doğru olacaktır ve böylece kullanıcıların yalnızca bir alt kümesi
uygulamayı kullanırken yeni diyalog ile karşılaşacaktır.</p>
      <p>Üçüncü kullanım örneğinde ise deneysel olarak başlangıçta yalnızca bazı
kullanıcılara göndermeyi düşündüğümüz bildirimler için bir kod bölgesi
görülmektedir. Bu defa dönemecimizin tipi bir String veri tipi dizisidir. Dönemeçten dönen
1 public void s e n d N o t i f i c a t i o n ( ) {
2 i f ( c o n t a i n s ( d . s t r i n g A r r a y (WHITELISTED_IPs) , CUSTOMER_IP) {
3 // only a c c e s s i b l e to c e r t a i n ip addresses .
4 . . .
5 }
6 }</p>
      <p>Tablo 1. Örnek dönemeç kullanımları
IP adresleri kullanıcının IP adresini içeriyorsa bildirimler gönderilir. Seçilmiş
kullanıcılar haricindeki kullanıcılar bu deneysel özelliği henüz göremezler.</p>
      <p>Tablo 2 olası dönemeç veri tipleri ve örnek kullanımlar görülmektedir. Çağrılan
fonksiyonların ikinci parametreleri verilen dönemeç bulunamadığında dönecek
varsayılan değeri gösterir.</p>
      <p>Dönemeç
Tipi
bool
integer
fraction
string
integerArray
stringArray
fractionArray
struct
Örnek kullanım
d.bool("new_optimization_on", false)
d.integer("threshold", 20)
d.fraction("p", 3.14)
d.string("name", "jack")
d.integerArray("myintarray", [120, 20, 30])
d.stringArray("mystringarray", ["jack", "jill"])
d.fractionArray("myFractionArray", [3.1, 2.7])
d.struct("mystruct", "sendToA" : 100, "sendToB" : 0)</p>
      <p>Tablo 2. Desteklenen dönemeç tipleri.
2.1</p>
      <p>Sistem Mimarisi
Önerdiğimiz sistemin mimarisini iki bölümde anlatacağız. Birinci bölümde
sistemi kullanan uygulamanın dönemeçleri nasıl sorguladığını göstereceğiz. İkinci
bölümde ise bir yönetim arayüzü vasıtasıyla dönemeçlerin nasıl yönetildiğinden
(yaratılma, güncellenme, zaman aşımına uğrama, silinme) bahsedeceğiz.
Dönemeçlerin uygulama tarafından sorgulanması: Şekil 1’de bir
uygulamanın dönemeç kütüphanesi ile nasıl etkileştiği görülmektedir. Dönemeç
kütüphanesinin sorgulama ile ilgili kısımları ana hatlarıyla dört bölümden
oluşmaktadır. Birinci bölüm uygulamanın doğrudan erişimine açılmış sorgulama
katmanıdır. Burada dönemeçlerin okunmasına yönelik çeşitli metotlar
bulunmaktadır. İkinci bölüm dönemeçlerin tutulduğu bir anahtar-değer deposu sistemine
erişimi ve aradaki iletişim protokolünü gerçekleştirebilen depolama katmanıdır.
Anahtar-değer depolama sistemi olarak Redis ve Memcached gibi birçok
alternatif teknolojiler mevcuttur. Bu çalışmada depolama sistemi olarak Redis[8]
kullanılmış ve Redis ile iletişimi sağlamak için ise Java dilinde yazılmış Jedis[9]
kütüphanesi seçilmiştir. Bu kütüphanenin en önemli avantajı birden fazla
Redis sisteminin küme (İng. cluster) olarak çalıştırıldığı durumları da destekliyor
olmasıdır.</p>
      <p>Bir başka bölüm ise dönemeç depolama sisteminden sık periyotlarla
dönemeçlerin en son değerlerini indirmektedir. Bu sayede dönemeçlerde olan
değişiklikler kısa sürede fark edilebilmektedir. Bu bölümün indirdiği değerler önbellek
biriminde saklanır. Uygulama dönemeç sorguları yaptığında ön bellekte olan
Şekil 1. Dönemeç sorgulama mimari diyagramı
dönemeç değerleri uygulamaya dönülür. Önbellek sayesinde uygulama dönemeç
değerlerine bloke olmadan ulaşabilmektedir. Böylece dönemeç kütüphanesi
kendisini kullanan bir uygulamaya herhangi kayda değer bir performans maliyeti
getirmemesi sağlanır. Uygulama açısından herhangi bir dönemecin değerine
ulaşmak hafızadaki herhangi bir değişkenin değerine ulaşmakla aynı maliyettedir.</p>
      <p>Şekil 1’de görüldüğü üzere uygulama öncelikle önbellek ve periyodik dönemeç
indirme bölümlerini oluşturur (1, 2, 3). Bu noktadan sonra dönemeçler dönemeç
depolama sisteminden periyodik olarak indirilir ve önbellek nesnesinde saklanır
(4, 5, 6). Uygulama bir dönemecin değerini sorgularsa dönemecin değeri yerel
olarak önbellek nesnesi vasıtasıyla cevaplanır (7, 8).</p>
      <p>Dönemeçlerin yönetimi: Şekil 2’de bir dönemeçlerin nasıl yönetildiği
görülmektedir. Dönemeçler oluşturuldukça dönemeçlerin neler olduğu ve hangi değerleri
içerdiği depolama sistemi sorgulanarak bulunabilir. Fakat bu bilgilerin yazılım
kaynak kodları gibi bir versiyon kontrol sistemi içerisinde tutulması
dönemeçlerin ve dönemeçleri kullanan yazılımların bakımını kolaylaştırır. Bu sebeple bir
dönemeç yaratılmak istendiğinde bir versiyon kontrol sistemine ulaşılır ve bu
sistemde dönemeç tanımlamalarını içeren dosyalar üzerinde gerekli değişiklikler
otomatik olarak yapılır. Bu sayede birden fazla kişinin aynı dönemeçleri
birbirine çatışır şekilde değiştirmesi önlenmiş olur. Aynı süreç var olan bir dönemeç
güncellenmek istendiğinde de izlenir.</p>
      <p>Şekil 2. Dönemeç yönetimi mimari Diyagramı</p>
      <p>Ayrıca bir dönemeç için bir son kullanma tarihi belirlenebilir. Bu tarihten
sonra dönemeç otomatik olarak anahtar-değer depolama sisteminden silinir.
Silinmiş bir dönemeç sorgulandığı durumda dönemecin veri tipine karşılık gelen
varsayılan değer dönülür. Son kullanma tarihi yazılımdaki deneysel özelliklerin
belirli bir tarihe kadar kullanımda kalmasını sağlar. Tarih geçtikten sonra
deneysel özelliklerin etkileri otomatik olarak ortadan kalkar. Bu da bu tür denemelerin
yönetimini kolaylaştırır.</p>
      <p>Dönemeçlerin Saklanması ve Ağ Üzerinden İletilmesi: Bu çalışmada
anahtar-değer depolama sistemi olarak Redis kullanılmaktadır. Dönemeç
kütüphanesi ile Redis arasında dönemeçlerin iletilebilmesi ve Redis’te saklanılması için
birçok format alternatifi kullanılabilir. Biz bu gerçekleştirmemizde JSON
formatını tercih ettik. Tablo 3’te JSON formatında serileştirilmiş dönemeç bilgileri
gösterilmiştir. Burada “value” dönemecin değerini ve “type” tipini
göstermektedir. Bunun yanında dönemecin zaman aşımına uğrayarak Redis üzerinden
silinmesi için bir zaman aşım tarihi görülmektedir (“expiration_date’). Bunlara ek
olarak bir dönemecin hangi maksatla oluşturulmuş olduğunun takibi için mesele
takip sistemini referanslayan mesele numarası (“issue_number’) ve dönemecin
değerinin en son ne şekilde güncellendiğinin takibi için kod versiyon sistemini
referanslayan güncelleme numarası (“commit”) da kaydedilen bilgiler arasındadır.</p>
      <p>Dönemeç
Tipi
fraction
fractionArray
struct
2.2</p>
      <p>Dönemeçlerin Kullanımı
Öncelikle dönemeçler bir dönemeç yönetim arayüzü vasıtasıyla tanımlanır. Daha
sonra tehlike arz eden veya deneysel olan kod değişiklikleri if-else bloğu içerisine
alınır ve if-bloğunun karar şartının doğruluğuna dönemeç kütüphanesi
sorgulanarak karar verilir. Burada dikkat edilmesi gereken husus sorgulamadan
dönemecin varsayılan değeri döndüğünde güvenli ve kararlı kod bölgesinin çalıştırılıyor
olmasıdır. Örneğin aşağıda bu kuralın yanlış bir uygulanışı görülmektedir.
if (d.bool(ENABLE_DANGEROUS_CHANGE, true)) { // false olmalıydı.
...//experimental
} else {
...//stable
}</p>
      <p>Aynı dönemeç, kaynak kodun farklı bölgelerini aktif hale getirmek için
kullanılabilir. Bu sayede kaynak kodun birçok bölgesine yayılmış olan bir
güncelleme kontrol altına alınabilir. Daha sonra dönemeçlerle etiketlenmiş yazılım,
üretim ortamlarına konuşlandırılır. Dönemeç yönetim arayüzü vasıtasıyla
dönemeç değerleri güncellenir. Saniyeler mertebesinde, yazılım, güncellenen dönemeç
değerlerinin etkisiyle yeni davranışlar göstermeye başlar. Herhangi bir sorunla
karşılaşıldığında dönemeç değerleri yeniden arayüz vasıtasıyla değiştirilerek ilgili
güncelleme devreden çıkarılır.</p>
      <p>Güncellemelerin hatalara yol açmadığı veya deneysel fikirlerin yeteri kadar
olgunlaştırıldığı kararına varıldığında kaynak kodlar içerisinde dönemeç değerleri
aranır. if-else blokları içerisine alınmış olan bölgeler temizlenerek yeni
özelliklerin varsayılan davranışlar olması sağlanır. Son olarak dönemeçler henüz zaman
aşımına uğramadıysa dönemeçler dönemeç yönetim arayüzü vasıtasıyla
depolama sisteminden silinebilir.
3</p>
      <p>İlgili Çalışmalar
Craig Larman yazılımlarda meydana gelecek değişikliklerle başa çıkmanın yolu
olarak "korunmuş değişimler" (İng. protected variations") tasarım desenini
önermiştir[10]. Bu desende konfigürasyon değerlerinin dış bir kaynaktan okunması
sağlanarak, istendiğinde yazılımların davranışlarının dinamik olarak
değiştirilmesi sağlanabilir. Bu çalışmadaki yaklaşım bu desen ile uyumludur. Martin
Fowler yazılım davranışlarının kontrolü için özellik bayrakları veya anahtarları
(İng. feature flags/toggles) kavramlarını ortaya koymuştur[11]. Bu tür yapıları
dört kategoriye ayırmıştır: izin anahtarları (İng. permission toggles), operasyon
anahtarları (İng. operations toggles), deney anahtarları (İng. experiment
toggles), salıverme anahtarları (İng. release toggles). Bu çalışmadaki yaklaşımımızda
bu kategorilerin tamamında özellik anahtarları tanımlamak mümkündür.</p>
      <p>Açık kaynak kodlu bir proje olan Togglz, bu çalışmada sunduğumuz sistem
ile birçok yönden benzeşmektedir[12], sunduğumuz sistemde birçok farklı tipte
dönemeç konfigüre edilebilmektedir. Bu sebeple Togglz yaklaşımına göre
Dönemeçler daha esnek bir karar verme stratejisini mümkün kılar. Yaklaşımızla
benzeşen LaunchDarkly[13] ve Rollout.io[14] gibi ticari servisler de mevcuttur. Fakat
operasyonel gizliliğin korunmasının tercih edildiği ortamlarda veya üçüncü parti
bir hizmete bağımlılığın oluşturulmak istenmediği sistemlerde bu ticari ürünlerin
kullanımı mümkün değildir.</p>
      <p>Yazılımlarda oluşan hataların otomatik olarak tespit edilmesi ve tamir edilmesi
ile ilgili Gazzola vd. son yıllarda yapılan çalışmaları derlemişlerdir[15]. Bu
çalışmalarda yazılımlar üzerinde statik ve dinamik analizler yaparak otomatik veya
yarı otomatik olarak tamir edici yamaların üretilmesi ve sisteme entegre edilmesi
hedeflenmektedir. Bu çalışmalardan farklı olarak bizim çalışmamızda hataların
tespitinin otomatikleştirilmesi konusunda herhangi bir efor bulunmamaktadır.
Fakat çalışmamızda bu çalışmaları tamamlayacak şekilde hatalı olduğunda ciddi
hasarlara yol açabilecek değişikliklerin kademeli olarak devreye alınması veya
devreden çıkarılmasını sağlayacak bir yaklaşım hedefledik.</p>
      <p>Tüm hasarların tamirini tamamen otomatik hale getirmek teknik olarak
mümkün değildir. Dolayısıyla üretim ortamlarında ortaya çıkan hataların
geliştiriciler tarafından tamir edilmesi uzun süreler alabilir. Bu sebeple rapor edilen
hataların arasında doğru biçimde önceliklendirme yaparak en fazla müşteriyi
etkileyen hataların belirlenmesi büyük önem arz eder. Kim vd., Firefox ve
Thunderbird ürünlerinin hata raporu veritabanları üzerinde çalışan otomatik bir analiz
geliştirmişler ve yüksek başarıyla hangi hataların öncelikle çözülmesi gerektiğini
tahmin edebilmişlerdir[5]. Bizim çalışmamız bu çalışmaları da tamamlayıcı
niteliktedir. Bazı hataların daha sonra tamir edilmesine karar verilse dahi tüm hatalı
davranışlar önerdiğimiz yaklaşım sayesinde hızlıca devreden çıkarılabilir.</p>
      <p>Yazılımların otomatik olarak konuşlandırılması üzerine birçok çalışma yapılmıştır.
Benson vd. bu çalışmaları derleyen bir çalışma yayınlamıştır[16]. Yazılım
sistemlerinin, bulut servis sağlayıcıları üzerinde, alana özgü programlama dilleri
vasıtasıyla konfigüre edilmesi ve güncellenmesi için Chef, SaltStack ve Ansible
gibi birçok teknoloji geliştirilmiştir[17]. Bu teknolojilerle yazılım unsurlarının
nasıl ve nereye konuşlandırılacağı ile birbirleriyle nasıl iletişime geçecekleri
belirlenmektedir. Böylece el yordamıyla yapılan birçok adımlar alana özgü dillerle
yazılmış programlar çalıştırılarak yapılabilmektedir[18]. Bu çalışmalardan farklı
olarak buradaki çalışmamızdaki amacımız sistemlerin konuşlanma
konfigürasyonunu kolaylaştırmak değil, sistemler üzerinde çalışan yazılımların davranışlarını
dinamik olarak değiştirebilmektir.
4</p>
    </sec>
    <sec id="sec-4">
      <title>Sonuçlar ve Gelecek Çalışmalar</title>
      <p>Bu çalışmada yazılımların dinamik olarak davranışlarının değiştirilebilmesini ve
dolayısıyla tehlikeli veya deneysel sayılabilecek kaynak kod güncellemelerinin
yönetimini kolaylaştıracak bir yaklaşım sunduk. Aynı zamanda bu yaklaşımı
uygulama tarafından kullanılacak bir kütüphane, dönemeç depolama sistemi
ve dönemeç yönetim arayüzü olarak pratiğe dönüştürdük. Bu sistemi finans
alanında çalışan bir yazılım firmasında kullandık. Sistem sayesinde hatalı yapıldığında
ciddi mali kayıplara yol açabilecek tehlikeli değişikliklerin kademeli olarak
devreye alınması sağlanmıştır. Aynı zamanda bu sistemle deneysel sayılabilecek
ve müşterinin geri bildirimine muhtaç olan yeni fikirlerin tüm kullanıcıları
etkilemeden hayata geçirilmesi ve test edilmesi mümkün kılınmıştır. Önümüzdeki
dönemde geliştirdiğimiz sistemimizi açık kaynak kod olarak diğer firmaların da
kullanımına sunmayı planlamaktayız. Aynı zamanda sistemimiz içerisine
istatiksel analiz yapabilecek bir başka alt sistem geliştirerek, dönemeçlerle yapılan
deneysel çalışmalara kullanıcı davranışlarının nasıl etkilendiğini gösteren
istatiksel geri bildirimler vermeyi hedefliyoruz.</p>
    </sec>
    <sec id="sec-5">
      <title>Kaynakça</title>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>Tony</given-names>
            <surname>Savor</surname>
          </string-name>
          , Mitchell Douglas, Michael Gentili,
          <string-name>
            <given-names>Laurie</given-names>
            <surname>Williams</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Kent</given-names>
            <surname>Beck</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Michael</given-names>
            <surname>Stumm</surname>
          </string-name>
          .
          <year>2016</year>
          .
          <article-title>Continuous Deployment at Facebook and OANDA</article-title>
          .
          <source>In Proceedings of the IEEE/ACM 38th International Conference on Software Engineering Companion</source>
          (
          <string-name>
            <surname>ICSE-C).</surname>
          </string-name>
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <given-names>Giovanni</given-names>
            <surname>Grano</surname>
          </string-name>
          , Adelina Ciurumelea, Sebastiano Panichella, Fabio Palomba,
          <string-name>
            <surname>Harald</surname>
            <given-names>C.</given-names>
          </string-name>
          <string-name>
            <surname>Gall</surname>
          </string-name>
          .
          <year>2018</year>
          .
          <article-title>Exploring the integration of user feedback in automated testing of Android applications</article-title>
          .
          <source>In Proceedings of the IEEE 25th Software Analysis Evolution and Reengineering</source>
          (SANER) International Conference on, pp.
          <fpage>72</fpage>
          -
          <lpage>83</lpage>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>