<!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>Olay Tabanlı Bir Yazılım Mimarisinde Bağımlılık İletimi ve Bileşen Gerçekleştirimi</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Orçun Dayıbaş</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Serdar Doğan</string-name>
          <email>serdardogan@aselsan.com.tr2</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Aselsan A.Ş. SST-MD-YMM</institution>
          ,
          <addr-line>P.K. 1 06172, Yenimahalle, Ankara</addr-line>
        </aff>
      </contrib-group>
      <abstract>
        <p>Özet. Olay yolu (Event Bus), yazılım bileşenleri arasında Yayımcı-Abone (Publish-Subscribe) tarzına uygun iletişim sağlayan ve bunu yaparken yazılım bileşenlerinin birbirlerinden haberdar olmasını gerektirmeyen bir yapıdır. Bağımlılık iletimi (Dependency Injection) de bileşen bağımlılıklarının dışarıdan iletilerek bileşenlerin yapılandırılabilmesine olanak sağlar. Mimarisi olay yolu üzerine kurgulanmış bir yazılımda bağımlılık iletimi kullanılması durumunda, bu iki yaklaşımın etkileşimi, denetim altına alınması gereken bir husus haline gelir. Bu çalışma kapsamında, sözü edilen denetimin yazılım geliştirme süreci içerisinde nasıl ele alınabileceği tartışılmıştır. Bu bağlamda, geliştirdiğimiz derinlik ölçüm sonarı (iskandil sistemi) grafiksel kullanıcı arayüz (GKA) yazılım mimarisine temel olan “Yolcu” çerçevesi ve ilgili proje kapsamında edinilen kullanım deneyimleri de makale kapsamında verilmiştir. Anahtar Kelimeler. Bağımlılık iletimi, Olay tabanlı yazılım mimarisi, Yeniden Kullanım, Olay yolu.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>
        Yazılım dünyasında üretkenliğin artırılması için ortaya konulan en temel
yöntemlerden biri yeniden kullanımdır. Yeniden kullanımın sistematik olarak desteklenmesi
için yazılım bileşenlerinin tasarım ve geliştirim süreçlerinin, bu temel üzerine
kurulması gerekir. Bu bağlamda yazılım mimarisi, yeniden kullanımı garanti altına almak
(sistematik hale getirmek) için bir araç olarak görülebilir. Yeniden kullanım odaklı bir
mimari tasarımda, nesne yönelimli tasarımın temel ilkelerinin (SOLID) gözetilmesi
gerektiği söylenebilir [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. Bu temel ilkelerin hepsi ya da bir kısmının, mimari
tarafından bileşen seviyesinde zorlanması yazılım kalitesini ve üretkenliğini artıracak bir
unsurdur.
      </p>
      <p>
        Bu makale kapsamında ele alınan durum çalışması, Aselsan bünyesinde tanımlı,
derinlik ölçüm sonarı grafiksel kullanıcı arayüzü yazılımı geliştirme sürecini
kapsamaktadır. İlgili yazılım, belirli bir proje ailesi (KULAÇ) için ortak kullanılması
öngörülerek geliştirilmiştir. Yazılım geliştirme ve analiz sürecinde yetenek tabanlı
bileşenler (ve yetenek gereksinimleri) çıkartılarak, yeni gelecek benzer projelerde de
bu varlıkların yeniden kullanılması hedeflenmiştir. Burada kurulması (o tarihte)
öngörülen altyapı, kısmen [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]’de tanımlanmış, bu makale kapsamında da tanımlanan
yöntemin nasıl uygulandığı ele alınmıştır (Yetenek modellerinin nasıl ele alındığına
dair detaylı bilgi için bkz. [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]).
      </p>
      <p>Makalenin geri kalanı şu şekilde düzenlenmiştir: İkinci bölümde yeteneklerin
varlıklarla nasıl ilişkilendirildiği ve yazılım gereksinim belgesi üzerinde nasıl ifade
edildiği verilmiştir (Problem alanının çözümlenmesi). Üçüncü bölüm, bileşenler arası
etkileşimlerin mimari seviyede nasıl ele alınacağı tartışılmış ve hemen ardından
dördüncü bölümde bu çalışmanın sonucu olarak ortaya konulan yeniden kullanılabilir
çerçevenin (Yolcu) detayları ve bileşenler arası etkileşimlerin bu çerçevede nasıl ele
alındığı belirtilmiştir. Çalışmanın sonuç ve değerlendirmesi de beşinci bölümde
verilmiştir.
2</p>
    </sec>
    <sec id="sec-2">
      <title>Yetenek Modeli ve Gereksinim Yönetimi</title>
      <p>
        Yazılım bileşenlerinin etkin yeniden kullanımı için gereksinim yönetimi önemli bir
unsurdur [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. Değişkenlik yönetiminin yetenek tabanlı [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ] yapıldığı bir ortamda,
gereksinimlerin tanımlarının da yetenekler ile ilişkilendirilmesi ihtiyacı ortaya
çıkmaktadır. Bu amaçla, projelerde kullandığımız YGÖ - Yazılım Gereksinim Özellikleri
(SRS) şablonuna aşağıdaki eklemeler yapılmıştır1:
 Yetenek Modeli: Yetenek modeli, yetenekler arasında sıradüzensel ve karşılıklı
ilişkileri gösteren modeldir [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ]. Proje kapsamında, yetenek modeli ağaç şeklinde
görselleştirilerek gereksinim belgesine (YGÖ) eklenmiş (bkz. Şekil 1) ve geçerli
yazılım ürünlerinin, modelin geçerli yapılandırmaları olacağına dair bir tanım
maddesi eklenmiştir.
      </p>
      <p>Şekil 1. KULAÇ GKA Yetenek Modeli
 Yetenek Bilgisi (Yetenek Kolonu): Gereksinimlerin ilgili olduğu yetenek(ler),
gereksinim yönetim aracı (Doors) üzerinde tanımlı şablona bir özellik olarak
eklenmiş ve yeni bir kolonda verilmiştir (bkz. Şekil 2). Bu sayede gereksinimler
yetenekler üzerinden sorgulanabilir hale gelmiştir (Doors’un sorgulama altyapısı
kullanılarak).</p>
      <p>
        Sürecin temel aldığı şablon J-STD-016 standardına dayanmaktadır [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ].
      </p>
      <p>Şekil 2. Doors Şablonuna Eklenen Yetenek Kolonu2
Yetenek gereksinimlerinin açıkça ifade edilmesi, hem bu yetenekleri sağlayan
bileşenlerin gereksinimlerine kolayca erişebilmek, hem de bileşen bağımlılıklarını
çıkarabilmek adına yarar sağlamıştır. Yetenek modelinin bir diğer faydası da sıradüzensel
bağımlılıkların, gereksinim gerçekleştirim önceliklerini belirlemek için
kullanılabilmesidir. Örneğin yetenek ağacındaki her bir yaprak düğümün (leaf node)
gerçekleştirim önceliği kendisini köke (temel yetenek) bağlayan düğümlerin gerçekleştirim
önceliğine eşit veya düşük olmalıdır. Aynı yorum, doğrudan gerektirme (“requires”
türü) bağımlılıkları için de yapılabilir.</p>
      <p>
        Yetenek modellerinin gerçekleştirimine ilişkin önerdiğimiz yaklaşım, [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]’de
detaylı olarak verildiğinden, bu makalenin kapsamı dışında tutulmuştur. Sözü edilen
yaklaşıma dair genel akış, Şekil 3’de gösterilmiştir.
      </p>
      <p>
        Şekil 3. Yetenekten Gerçekleştirime Yarı Otomatik Geçiş [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]
2 Madde metinleri ticari gizlilik açısından karartılmıştır.
      </p>
      <p>Yazılım</p>
    </sec>
    <sec id="sec-3">
      <title>Mimarilerinde Bileşen Etkileşimleri</title>
      <p>
        Nesne yönelimli bir mimaride, yazılım bileşenleri arasındaki etkileşimler iki temel
sınıfta ele alınabilir; olgu yaratma ve iş akışı çağrıları:
 Olgu Yaratma: Bir nesne, bağımlı olduğu soyutlama (Ör: Arayüz tanımı)
üzerinden bir nesnenin olgusunu yaratamaz. Ayrıca nesnelerin olgularının yaratılması
soyutlama üzerinden yapılsa da nesneye doğrudan bağımlılık oluşturur. Bu durum,
“Soyutlamalara bağımlı ol, gerçekleştirimlere bağımlı olma” ilkesinin ihlali
anlamına gelir [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. Bu durumu ortadan kaldırmak için soyut fabrikalar [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ], bağımlılık
iletimi [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ] vb. yöntemler yaygın olarak kullanılmaktadır. Bu çalışma kapsamında
nesne yaratımına ilişkin detayların uygulama kodundan tamamen soyutlanması ve
sınanmış bir çerçeve kullanımına olanak tanımak adına açık kaynaklı bir bağımlılık
iletimi çerçevesi olan “Google Guice” [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ] kullanımı tercih edilmiştir (bkz. Şekil 3).
 İş Akışı Çağrıları: Nesneler bir araya gelerek bir kullanım senaryosunu işletirken,
çoğunlukla belirli bir iş akışını izleyen çağrılar yaparlar. Bu çağrıların doğrudan
yapılması bağlaşımı (coupling) artıran ve dolayısı ile yeniden kullanımı zorlaştıran
bir unsurdur. Bu duruma çözüm olarak da servis tabanlı [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ], olay tabanlı [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] vb.
mimarilerin kullanımı değerlendirilebilir. Başarımı en az etkileyecek şekilde
bağlaşımı azaltacak bir çözüm bulmak ve bir önceki maddede belirtildiği gibi yine
sınanmış bir çerçeve kullanmak adına “Google Guava EventBus” [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ] kullanımı
tercih edilmiştir.
      </p>
      <p>Olay tabanlı bir mimaride çağrıyı yapan ve çağrıya cevap veren bileşenler arasında
doğrudan bir bağımlılık yoktur. İş akışı, “Olay Yolu” üzerinden iletilen “olay”lar ile
gerçekleşir (bkz. Şekil 4). Olay yolu, yayınlanan bir olayı, o olayı dinleyen tüm
abonelere iletir (Yayımcı-Abone). Bu yaklaşımda, her ne kadar yazılım bileşenlerinin
birbirlerine doğrudan bağımlılıkları olmasa da iletişim için ilgili olay türlerini
bilmeleri gerekir (Bileşenler olay türlerine bağımlıdır). Bu bağlamda, birbirlerinin
arayüzlerini bilmeyen bileşenler arasındaki iletişimi sağlayabilmek için ortak bir dilin
tanımlanması ihtiyacı doğmaktadır. Bu dil, olay yolu üzerinden gidip gelecek nesne
türlerinin (olay) belirlenmesi ile tanımlanır.</p>
      <p>Şekil 4. KULAÇ GKA Yazılımında Olgu Yaratma (A) ve İş Akışı (B) Bileşen Etkileşimleri
Olay tabanlı olmayan bir yapıdaki her farklı yöntem çağrısı, olay tabanlı yapıda yeni
bir olay türüne karşılık gelmektedir. Bu durum, her ne kadar küçük ölçekli yazılımlar
için kabul edilebilir olsa da yazılım ölçeği büyüdükçe çok sayıda olay türü
tanımlanması, bazı yan etkilere yol açabilir. Bunlara örnek olarak kodun idame
edilebilirliğinin azalması ve hata ayıklamanın zorlaşması verilebilir. Bu problemlerin oluşmasını
önlemek adına önerilen çerçevede olay kullanımı kurallarla sınırlandırılmıştır (bkz. 4.
Bölüm).
4</p>
    </sec>
    <sec id="sec-4">
      <title>Yolcu Çerçevesi</title>
      <p>Yolcu çerçevesi, veri paylaşımı ve iş akışı tetikleme altyapısı olarak olay yolu
kullanımını benimseyen yazılımlar için geliştirilmiş bir çerçevedir. Yolcu çerçevesi
kullanılarak geliştirilmiş bir uygulamanın merkezinde üç temel unsur yer alır; “Olay
Yolu”, “Kullanıcı Arayüzü Yönetici” (KA Yönetici) ve “İş Yönetici”. Olay yolu,
platform ya da kullanıcı kaynaklı olayların ilgili birimlere (aboneler) iletilmesinden
sorumludur. “Kullanıcı Arayüzü Yönetici”, yazılımın kullanıcı ile olan etkileşiminden
sorumlu bileşenler (veri girişi, veri görüntüleme), “İş Yönetici” ise bir veya birden
çok kullanım durumunun (senaryo) gerçekleştirilmesinde rol oynayan, iş mantığının
gerçeklendiği ya da alt katman soyutlamalarının kullanımı ve yönetiminden sorumlu
bileşenlerdir.</p>
      <p>Yolcu çerçevesi temelde çok katmanlı bir grafiksel kullanıcı arayüzü uygulama
geliştirme altyapısı sunar (bkz. Şekil 5). En üst seviyede kullanıcı arayüzü katmanı, altta
iş mantığı katmanı ve aralarında olay tabanlı iletişimi sağlayan olay yolu bulunur.</p>
      <p>Şekil 5. Katmanlı Mimari ve Yolcu Çerçevesinin Yeri
Olay yolu için olayı yayınlayan ya da dinleyen yöneticilerin hangi katmanda
olduğunun ya da iletişimin hangi yönde olduğunun bir önemi yoktur. İki yönde de
olaylar kaynağı ya da hedefi sorgulanmadan iletilir. İletişim yönü için bir kısıt
olmaması, gerçekleştirim sırasında döngüsel bağımlılık kurulmasına neden olabilir. Bu
ve benzeri sorunların önüne geçmek için Yolcu çerçevesi, yazılım katmanları ve
bileşenler arasındaki iletişimi sınırlandırmaktadır. İzin verilen bileşen etkileşimleri ve bu
etkileşimlere dair açıklamalar aşağıda verilmiştir:</p>
      <p>Şekil 6. Yolcu Çerçevesi Bileşen Etkileşim Kuralları
1. Kullanıcı Arayüz (KA) yöneticilerin yayınladığı olaylardır. Bir iş akışı başlatan
kullanıcı girdileri (Ör: Kullanıcının bir menü düğmesine basması), olay olarak
yayınlanır. Bir KA yönetici başka bir KA yöneticiye doğrudan erişmez ya da
kullanıcı girdilerini ifade etmek için tanımlanmış olayları dinleyemez. KA yöneticilerin
kullanım durumları kapsamında yönetim sorumluluğu, iş yöneticilere devredilerek,
KA katmanındaki bileşen bağımlılıkları ortadan kaldırılmaya çalışılmıştır.
2. İş yöneticilerin dinlediği olaylardır. İş yöneticiler, kullanım durumu başlatan KA
olaylarını ya da diğer iş yöneticilerin yayınladığı olayları dinlerler.
3. KA yöneticiler, iş yöneticilerin yayınladığı olayları dinlerler. Bunlar bir kullanım
durumu kapsamında alt iş adımları olabileceği gibi alt katman soyutlamalarından
sorumlu iş yöneticilerin yayınladığı olaylar (DDS verileri, seri kanal girdileri vb.)
da olabilir.
4. İş yöneticilerin yayınladığı olaylardır. İş yöneticilerin yayınladıkları olaylar hem
diğer iş yöneticileri hem de KA yöneticileri ilgilendiriyor olabilir.
5. Kullanım durumu alt adımları doğrudan yöntem çağrısı ile yapılır (zaman uyumsuz
olarak yayınlanması gereken bir olay varsa yine yayınlanabilir). Bu bağımlılıklar,
arayüzler üzerinden ve bağımlılık iletimi ile (bkz. 3. Bölüm) kurulduğundan,
çalışma zamanında KA yönetici gerçekleştirimini değiştirmek de mümkündür.
6. Zaman uyumlu işletilen kullanım durumu adımlarında bir iş yönetici diğer bir iş
yöneticiyi doğrudan kullanabilir. Bu bağımlılıklar da yine bağımlılık iletimi
yöntemi ile kurulur.</p>
    </sec>
    <sec id="sec-5">
      <title>Sonuç ve Değerlendirme</title>
      <p>KULAÇ proje ailesi için GKA yazılımı geliştirme işleri kapsamında ortaya konulan
ve bu makalede detayları verilen yaklaşımlar ile aşağıdaki kazançlar sağlanmıştır:
 Yeniden kullanılabilir varlıklar (bileşen ve gereksinimler), yetenek tanımları ile
ilişkilendirilerek, üst seviye bir soyutlama ile projeler arası benzerliklerin ele
alınabilmesi için ortam hazırlanmıştır. Toplam 316 gereksinim maddesi, 24 yetenek
ile ilişkilendirilmiştir. Bu gereksinimlerin 199 adedi temel yetenek ile
ilişkilendirilmiştir. Proje ailesinin büyümesi ile yetenek sayısının artacağı ve temel yeteneğin
küçüleceği öngörülmektedir.
 Bileşenlerin olgu yaratma kodları bağımlılık iletimi çerçevesi, iş akışı çağrıları da
olay yolu çerçevesi tarafından ele alındığından iş mantığı kodunda önemli bir
sadeleşme elde edilmiştir. Ayar ve akış denetim kodlarının (“Boilerplate” kodlar)
ortadan kalması, daha okunur ve daha kolay yönetilebilir bir kod yapısı
oluşturulabilmesine olanak tanımıştır (bkz. Çizelge 1: KGBYKB, bir su üstü KULAÇ projesi
için kodlanmış eski GKA yazılımı. KAYKB, yeni yaklaşımla kodlanmış, hem su
üstü hem de su altı projesi için gerekli yeteneklerini kapsayan ortaklanmış GKA
yazılımı).
KULAÇ
KGBYKB
(2011)
10.10%
10.03
285
45,133
4,057
88
850
6,798</p>
      <p>KULAÇ
KAYKB
(2013)
16.10%
9.75
200
19,747
1,458
39
341
2,623
İlerleyen dönemde, sözü edilen kazançların başka proje ailelerinde de
kullanılabilmesi adına geliştirilen Yolcu çerçevesi ve kullanım ilkelerinin diğer proje ekipleri
ile de paylaşılması öngörülmektedir.
3
Ölçümler için “CodePro Analytix” kullanılmıştır. Ölçüm isimleri, tekrarlanabilirliği
sağlamak için araçta olduğu haliyle (İngilizce) verilmiştir. Daha ayrıntılı bilgi için:
http://developers.google.com/java-dev-tools/code</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1. R.C. Martin, “
          <article-title>Design Principles and Design Patterns”</article-title>
          , Object
          <string-name>
            <surname>Mentor</surname>
          </string-name>
          (
          <year>2000</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <given-names>O.</given-names>
            <surname>Dayıbaş</surname>
          </string-name>
          , “
          <article-title>Yetenek Modellerinin Gerçekleştirimi Üzerine Bir Durum Çalışması”</article-title>
          ,
          <source>UYMK</source>
          (
          <year>2012</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>K.</given-names>
            <surname>Pohl</surname>
          </string-name>
          , “Requirements Engineering: Fundamentals, Principles, and Techniques”, Springer (
          <year>2010</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <given-names>K.</given-names>
            <surname>Kang</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Cohen</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Hess</surname>
          </string-name>
          ,
          <string-name>
            <given-names>W.</given-names>
            <surname>Novak</surname>
          </string-name>
          , S. Peterson, “
          <article-title>Feature Oriented Domain Analysis (FODA) Feasibility Study”</article-title>
          ,
          <source>Technical Report CMU/</source>
          SEI-90
          <string-name>
            <surname>-</surname>
          </string-name>
          TR-
          <volume>021</volume>
          (
          <year>1990</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <given-names>R.</given-names>
            <surname>Sorensen</surname>
          </string-name>
          , “
          <article-title>MIL-STD-498,</article-title>
          <string-name>
            <surname>J-</surname>
          </string-name>
          STD-
          <volume>016</volume>
          , and the U.S. Commercial Standard”,
          <source>CrossTalk</source>
          (
          <year>1996</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <given-names>E.</given-names>
            <surname>Gamma</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Helm</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Johnson</surname>
          </string-name>
          , J. Vlissides, “
          <article-title>Design Patterns: Elements of Reusable Object-Oriented Software”</article-title>
          , Addison
          <string-name>
            <surname>Wesley</surname>
          </string-name>
          (
          <year>1994</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <given-names>M.</given-names>
            <surname>Fowler</surname>
          </string-name>
          ,
          <article-title>"Inversion of Control Containers and the Dependency Injection Pattern"</article-title>
          , http://martinfowler.com/articles/injection.html (
          <year>2004</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <surname>“Google Guice - A Lightweight Dependency Injection Framework</surname>
          </string-name>
          ”, http://code.google.com/p/google-guice
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <given-names>N.</given-names>
            <surname>Bartlett</surname>
          </string-name>
          , “OSGi in Practice”, Draft Preview http://njbartlett.name/osgibook.html (
          <year>2009</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10. D. Garlan “
          <article-title>Formal Modeling and Analysis of Software Architecture Components</article-title>
          , Connectors, and Events”,
          <source>Formal Methods for Software Architecture LNCS</source>
          Vol.
          <volume>2804</volume>
          (
          <year>2003</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11. “Guava:
          <article-title>Google Core Libraries for Java 1</article-title>
          .6+”, http://code.google.com/p/ guava-libraries
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>