<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Bimar Teknoloji Blog - Medium]]></title>
        <description><![CDATA[Bimar Teknoloji - Medium]]></description>
        <link>https://medium.com/bimar-teknoloji?source=rss----92f06038ce70---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Bimar Teknoloji Blog - Medium</title>
            <link>https://medium.com/bimar-teknoloji?source=rss----92f06038ce70---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 17:09:23 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/bimar-teknoloji" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Bir PBI’ı Kurtaran Basit Tablo]]></title>
            <link>https://medium.com/bimar-teknoloji/bir-pbiyi-kurtaran-basit-tablo-44f89fb696fa?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/44f89fb696fa</guid>
            <category><![CDATA[yazilim-gelistirme]]></category>
            <category><![CDATA[grooming]]></category>
            <category><![CDATA[i̇ş-analizi]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Thu, 05 Mar 2026 11:13:13 GMT</pubDate>
            <atom:updated>2026-03-05T11:13:35.848Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*Dlb-EA_LQYxX80cdbipEIg.png" /></figure><p>Grooming toplantısında Hakan sessizce kalktı, tahtaya bir tablo çizdi. Sonra söz aldı. Ben bu konuşulanlardan hiçbir şey anlamadım. Olası senaryoları çıkardım. Bunların her biri için ne yapacağımızı konuşabilir miyiz? dedi.. Bir iş maddesini hazır hale getirmek için atılmış ufacık ama çok etkili bir yöntem. Bu tablonun sonra testlerde kullanılması da cabası.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/440/1*koGIMufzrtqiEePVvM58fA.png" /></figure><p>Başka bir örnek benim kişisel arşivimden gelsin. Sorun bana, <em>abi bazı senaryolarda istediğimiz sonucu alamıyoruz, sistem düzgün gibi sen de bir bakar mısın diye geldi</em>. CLOP NCLOP tekerleme gibi dinlerken iyice çorba oldu. Neyse sonra 2 dakikada şu tabloyu çizdik. Her biri için olması gerekeni söyledi. Yazdık. İş bitti. Artık IF’ini ELSE’ini bile buraya bakarak yazmıştır diye tahmin ediyorum.</p><p><em>( Sinan Yılmaz hocamızın ruhu şad olsun, ne zaman böyle bir tablo çizsem aklıma hep onun dersi gelir.)</em></p><h3>Sözün özü: Belirsizlik ve karmaşıklık durumunda, konuya biraz sistematik yaklaşmak bile çözüm yolunda büyük bir adımdır.</h3><p>Sağlıkla kalın,</p><p>Serkan</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=44f89fb696fa" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/bir-pbiyi-kurtaran-basit-tablo-44f89fb696fa">Bir PBI’ı Kurtaran Basit Tablo</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Redis Pub/Sub ile Cache Invalidation Yönetimi]]></title>
            <link>https://medium.com/bimar-teknoloji/redis-pub-sub-ile-cache-invalidation-dbf13f16924d?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/dbf13f16924d</guid>
            <category><![CDATA[redis]]></category>
            <category><![CDATA[cache-invalidation]]></category>
            <category><![CDATA[redis-pub-sub]]></category>
            <category><![CDATA[pub-sub-pattern]]></category>
            <dc:creator><![CDATA[Gürkan Şafak]]></dc:creator>
            <pubDate>Mon, 22 Dec 2025 10:06:16 GMT</pubDate>
            <atom:updated>2025-12-22T10:06:15.442Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JGFPt0N7xEUgrp5X87yz9g.png" /></figure><h3>Redis Pub/Sub İle Cache Invalidation Yönetimi</h3><blockquote>Redis birçok kişi tarafından hızlı bir cache yönetim aracı olarak bilinmektedir. Bu özelliğinin yanında kuyruk, session yönetimi ve mesajlaşma altyapısı gibi farklı özellikleri de içinde barındırıyor. Bu yazı içeriğinde redis’in pub/sub (publish/subscribe) özelliği ile şirket olarak cache üzerinde tuttuğumuz veriler güncellendiğinde bu durumdan nasıl haberdar olduğumuzu ve sonucunda onları nasıl tazelediğimizden bahsedeceğim.</blockquote><p>Cache’te tutulan veriler uygulamalar için büyük bir nimet. Sürekli veritabanından okumanız gereken, çok sık ulaşılan fakat çok sık değişmeyen verileri veritabanından tekrar tekrar çekmek yerine birçok uygulama cache’leme mantığını kullanmaktadır. Cache üzerinden çekilen veriler ile uygulamalar toplamdaki response sürelerini önemli ölçüde azaltıyor.</p><p>Fakat veritabanında tutulan verilerde bir değişiklik olduğu durumda gerçeğin bir yansıması olan cache’teki bu kopya verilerin de güncelliğini koruyor olması gerekli. Mesela kullanıcı bilgilerinin tutulduğu verileri düşünelim, uygulamaya ilk defa bir request geldiğinde kullanıcı bilgisine ihtiyaç duyuluyorsa önce cache’e bakılır, cache’de varsa kullanılır yoksa aktif tüm kullanıcılar veritabanından çekilerek cache’e atılır ve sonraki gelen istekler de kullanıcı cache bilgisi dolu olduğundan hep buradaki veri üzerinden cevap verilerek veritabanına tekrar tekrar gidilmez. Eğer kullanıcılardan herhangi birinin verisinde bir değişiklik olup veritabanı güncellemesi gerçekleşirse cache’teki bu bilgilerin de yeni veriler ile “tazelenmesi” gerekir. Aksi durumda uygulama cache üzerindeki verileri kullanmaya devam edeceği için güncel bilgiler ile işlem yapamadığından hatalı bir duruma yol açacaktır.</p><p>Temel anlamda cache’in beslendiği kaynak bilgilerinin değişimi ve bu durumda cache’in yeniden güncellenmesi işi terminolojik açıdan <em>cache invalidation</em> şeklinde ifade ediliyor. Bu girişten sonra biraz da bizim uygulamamızın yapısından, karşılaştığımız sorundan ve redis pubsub ile cache temizleme işini nasıl yaptığımızdan bahsetmek istiyorum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/503/1*yAiFcBmG3ytmPnNvnR3cRQ.png" /></figure><p>Uygulamamız 3 farklı sunucu üzerinde arkada load balancer yapısı ile yönlendirilen requestleri karşılayacak şekilde windows işletim sistemli serverlar üzerinde host ediliyor ve requestler sticky session mantığında işletiliyor. Kullanıcı ilk requestte hangi sunucuya yönlendirilmişse sonraki tüm istekler o sunucuya gidiyor. Birden fazla sunucu üzerinde aynı uygulamanın host edilmesi ve her sunucu üzerinde çalışan app’in kendi cache’ini kendi sunucu belleğinde tutması redis pub/sub’ı kullanmamızdaki ana motivasyon kaynağımızdı.</p><p>Farkındaysanız bu açıdan bakıldığında yaşadığımız problem biraz daha belirginleşmeye başlıyor. 3 farklı sunucu var, sticky session yönlendirme yapılıyor ve cache’lerdeki veriler bu 3 sunucu üzerindeki bellek birimlerinde birbirlerinden habersiz olarak tutulmakta. Sunuculardan biri üzerinde çalışan uygulama cache verisiyle ilgili bir değişiklik yaptığında sadece kendi belleğini temizleyerek yeni veriyi görmeye devam ediyor, fakat geriye kalan diğer 2 sunucudaki cache’ler bu temizlik işleminden haberleri olmadığı için hala eski veriyi kullanmaya devam etme riskiyle karşı karşıya, ta ki uygulamaya ait process stop/start edilene kadar.</p><p>Bu eski yapıda kullanıcılar tarafından genellikle şöyle geri bildirimler alınıyorduk; bazı kullanıcılar bir işlemi yapmaya devam edebilirken diğerleri edemiyor veya cache’te tutulan bilgi client tarafta bölgesel bazlı bir kısıtlamaya hizmet ediyorsa yine kullanıcıların bir kısmı (İspanya’daki kullanıcı işlem yaparken Mısır’dakinin yapamaması gibi) ekranlarında bu özelliğin yansımasını görürken geri kalan kısım göremiyordu. Bu durumun tek sebebi cache’in sunuculardan birinde güncellenmiş olması fakat diğer sunuculardaki cache’lerin eski veriyle çalışmayı sürdürmesiydi.</p><h4>1. Redis Pub/Sub ile Tanışma</h4><p>Bu noktada kısa bir araştırma ve POC çalışması sonrasında pub/sub’ın hazır olarak sunulan socket haberleşme altyapısını kullanarak cache invalidation işlemini yönetebileceğimizi gördük. Redis pub/sub built-in bir kütüphane olarak Redis sdk’ları ile birlikte kullanılabilir olarak geliyor. Kendi projemizde yapmamız gereken şey bu yapıyı ilgili projemize entegre ederek kullanmaktı.</p><p>İnternet araştırmamız sırasında bir github repo’su olarak redis altyapısında kullanacağımız publish, subscribe, redis connection açma gibi işlemleri kendi bünyesinde barındıran bir projeye denk geldik ve bu projedeki wrapper sınıfları kendi projemizde kullanarak redis pub/sub altyapısını hızlı bir şekilde oluşturabildik. Bu repo’ya şu link ile ulaşabilirsiniz 👇</p><p><a href="https://github.com/antoinebidault/MemoryCacheRedisBackplane.Net">GitHub - antoinebidault/MemoryCacheRedisBackplane.Net</a></p><p>Bu projeden beslenip kendi projemizde değişiklikler yaparken en çok dikkat ettiğimiz kısım uygulama ayağa kalktığında kullanılacak redis nesnesinin -ki bunun üzerinden connection ve pub/sub işlemlerini yürütüyoruz- singleton olarak implement edilmesiydi. Bu kullanım ile birlikte nesnenin sürekli oluşturulma hususundaki belleğe olan olumsuz etkisi ve concurrent işlemler üzerindeki sürprizlere gebe olabilecek endişelerimizden sıyrılmış olduk.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/523/1*ffti6j-0E3I8sSNOWiHI3A.png" /><figcaption>Redis Pub/Sub Cache Invalidation</figcaption></figure><p>Yukarıdaki şemada pub/sub ile gitmek istediğimiz noktayı özetlemeye çalıştım. Senaryomuzda 1 numaralı sunucuda çalışan uygulamamızda “KullaniciAppCache” anahtarı ile cache’te tutulan bilgiler üzerinde bir değişiklik olduğunu farz edelim. Bu durumda 1 numaralı sunucudaki uygulama önce veritabanına gidip kullanıcı bilgilerini güncelleyecek sonrasında bu işlemi yaptığından “doğal olarak” haberdar olduğu için kendi belleğindeki bu key ile tutulan cache’i silmesi gerekir. 1 numaralı işlem bunu yapmaktadır. Cache üzerindeki bu bilgi silindiği için bu sunucuda kullanıcı bilgisine ilk defa ihtiyaç duyulduğu anda veritabanından çekilecek ve sonra cache’e yazılarak oradan okunmaya devam edilecek. Yani 1 numaralı sunucuda çalışan uygulama <em>kendini kurtardı</em> yani taze bilgiyi cache’ten okuyabiliyor, fakat cache’in kirlendiği bilgisini 2 ve 3 numaralı sunucularla da paylaşması gerekiyor ki onlar da kendi cache’lerini temizlesinler.</p><p>2. işlemde aşağıda gördüğünüz gibi Redis sunucusuna bir anahtar ile birlikte sinyal gönderiliyor. Bu sinyali yakalayan redis pub/sub yapısı “daha önceden” kendisine kaydolmuş olan uygulamalara “bakın bu key artık güncel değil” mesajı ileterek uygulamaların kendi cache’ini temizlemesini sağlıyor. Bu işlemler de yukarıda yeşil daire içinde gördüğünüz 3 ve 4 numaralı adımla yapılıyor.</p><p>Bu döngü cache üzerinde tutulan her veri için eğer o verinin tutulduğu veritabanında bir değişiklik olmuşsa tetikleniyor, bu noktada tetikleme işlemini yapan noktanın ilk veritabanı güncellemesi yapan kod olduğunu unutmayalım. Böylece herhangi bir sunucu üzerinde çalışan uygulamanın kirlettiği cache’ten pub/sub yapısı ile birlikte diğer sunucularda çalışan uygulamaların da haberi oluyor.</p><p>Pub/Sub yapısı bir merkeziyet sağlayarak uydu uygulamaların cache konusunda birbirlerinden haberdar olmasına katkı sağlıyor.</p><h4>2. Pub/Sub Proje İçi Kodlama Detayları</h4><p>Yukarıda pub/sub’ın çalışma prensiplerine değindik. Bu bölümde ise uygulama tarafında kodlama sürecini adım adım açıklayacağım.</p><p><strong><em>2.1. Azure üzerinde Redis kaynağının oluşturulması.</em></strong></p><p>Şirket olarak Azure ekosisteminde çalıştığımız için öncelikle burada bir Redis kaynağına ihtiyacımız vardı. Bunu oluşturarak uygulamaların bağlanacağı kaynak ihtiyacını gidermiş olduk. Oluşturduğumuz Azure kaynağındaki hostname ve connection bilgilerini alarak uygulamamızın config bilgilerine ekledik.</p><p><strong><em>2.2. Redis pub/sub backplane yapısının projeye dahil edilmesi.</em></strong></p><p>Bu aşamada, Redis pub/sub mekanizmasını kullanarak mevcut cache temizleme sınıflarını değiştirmemiz gerekiyordu. Bu süreçte, GitHub üzerinde işimizi kolaylaştıran ve pub/sub metodlarını içeren wrapper sınıflarının bulunduğu bir backplane projesine denk geldik. Yukarıda bağlantısını paylaştım; ihtiyacınız olursa siz de kullanabilirsiniz. Bu sınıfları projemizdeki ilgili yardımcı sınıflar üzerinden çağırarak hangi aşamada publish işlemi yapacağımızı ve hangi noktalarda cache temizliği gerçekleştireceğimizi belirledik.</p><p>Aşağıda ilgili github reposundaki connect, subscribe ve publish metotlarının nasıl kullanıldığını görebilirsiniz;</p><p>(<a href="https://github.com/antoinebidault/MemoryCacheRedisBackplane.Net">https://github.com/antoinebidault/MemoryCacheRedisBackplane.Net</a>)</p><pre> public sealed class RedisService : IDisposable<br> {<br>     private ConnectionMultiplexer _redis;<br>     private int _retry = 1;<br>     private DateTime? _lastFailureDate = null;<br>     private Guid _originId;<br>     private readonly MemoryCacheRedisBackplaneOptions _options;<br>     private ISubscriber _sub;<br><br>     internal RedisService(MemoryCacheRedisBackplaneOptions options)<br>     {<br>         this._originId = Guid.NewGuid();<br>         this._options = options;<br>         this.Connect(options.RedisConnectionString);<br>         _redis.ConnectionFailed += (s, e) =&gt;<br>         {<br>             if (_retry &lt; options.NbRetry || _lastFailureDate &gt; DateTime.UtcNow.AddMinutes(5))<br>             {<br>                 Connect(options.RedisConnectionString);<br>                 _retry++;<br>             }<br>             _lastFailureDate = DateTime.UtcNow;<br>         };<br>     }<br><br>     internal void Connect(string cnx)<br>     {<br>         _redis = ConnectionMultiplexer.Connect(cnx);<br>         if (_redis.IsConnected)<br>         {<br>             _retry = 0;<br>         }<br>         _sub = _redis.GetSubscriber();<br>     }<br><br>     internal void Subscribe(Action&lt;string&gt; subscriptionCallback)<br>     {<br>         _sub.Subscribe(_options.EventSubscriptionName, (channel, message) =&gt;<br>         {<br>             if (message.HasValue)<br>             {<br>                 string value = message.ToString();<br>                 if (value.StartsWith(_originId.ToString()))<br>                 {<br>                     return;<br>                 }<br><br>                 subscriptionCallback(RemoveOriginId(value));<br>             }<br>         }, CommandFlags.FireAndForget);<br>     }<br>     <br>     internal void Publish(string key)<br>     {<br>         if (_redis.IsConnected)<br>         {<br>             _sub.Publish(_options.EventSubscriptionName, AppendOriginId(key), CommandFlags.FireAndForget);<br>         }<br>     }<br><br>     public void Dispose()<br>     {<br>         _sub.Unsubscribe(_options.EventSubscriptionName);<br>         _redis.Close();<br>         _redis.Dispose();<br>     }<br><br>     /// &lt;summary&gt;<br>     /// Append the origin id to the key in order to identify the request origin<br>     /// &lt;/summary&gt;<br>     private string AppendOriginId(string key)<br>     {<br>         return _originId.ToString() + &quot;_&quot; + key;<br>     }<br><br>     /// &lt;summary&gt;<br>     /// Remove the origin id from string<br>     /// &lt;/summary&gt;<br>     private string RemoveOriginId(string key)<br>     {<br>         return key.Substring(key.IndexOf(&quot;_&quot;) + 1, key.Length - key.IndexOf(&quot;_&quot;) - 1);<br>     }<br> }</pre><p><strong><em>2.3. Uygulama ayağa kalktığı sırada redis sunucusuna register olunması.</em></strong></p><p>Son aşama ise uygulama ilk nefes almaya başladığı anda hangi sunucu veya process üzerinde çalışıyorsa farketmez ilk yapacağı iş kendini “redis merkezi komutanlığına” bildirmek olmalı. Yani subscribe işlemini yapmalı kendini kayıt ettirmeli ki böylece ben sana gelecek olan değişikliklerden haberdar olmak istiyorum bilgisini önceden vermiş olsun.</p><p>Bu kısmı da bizim kullandığımız 2 tür runtime ortamı olduğundan farklı sınıflar içerisinde yaptık. .NET 4.8 framework ile çalışan webform uygulaması için global.asax.cs içinde .NET6 ile çalışan runtime içinse startup.cs sınıfı içinde bu işlemleri gerçekleştirdik.</p><p>Global.asax.cs sınıfı (4.8 framework için);</p><pre>public class Global : System.Web.HttpApplication<br>{<br><br>    protected void Application_Start(object sender, EventArgs e)<br>    {<br>        //Redis publish and subscribe mekanizmasi icin ilklendiriliyor..<br>        if (ConfigHelper.RedisCacheInvalidationDevredeMi)<br>            MemoryCacheRedisBackplane.Net.MemoryCacheRedisBackplane.Instance(AppMemoryCache.Instance());<br>    }<br>    <br>}</pre><p>Startup.cs sınıfı (.net core api projesi için);</p><pre>#region Redis&amp;Memory<br>AppMemoryCache.Configure(app.Services.GetRequiredService&lt;IMemoryCache&gt;());<br>if (ConfigHelper.RedisCacheInvalidationDevredeMi)<br>{<br>    MemoryCacheRedisBackplane.Net.MemoryCacheRedisBackplane.Instance(AppMemoryCache.Instance()); // Redis pub/sub registration..<br>}<br>#endregion</pre><p>Bu yazıda Redis pub/sub ile gerçek zamanlı cache invalidation yönetimi üzerine deneyimlerimi aktardım. Bu yaklaşımın, benzer sorunlarla karşılaşan geliştiricilere pratik bir çözüm sunacağını umuyorum. Okuduğunuz için teşekkürler.</p><p><em>Bilgisayar bilimlerinin göreceli olarak zor işlerinden biri olduğu düşünülen cache invalidation’a ilginiz varsa muhtemelen diğer bir zor konu olan isimlendirme için yazılmış temiz bir içeriğe hayır demeyeceğinizi tahmin ediyorum. Eğer o konu hakkında da merakınız taze ise şu yazıya göz atmanızı tavsiye ederim</em> 👇<br><a href="https://medium.com/bimar-teknoloji/sahadan-temiz-kod-i%CC%87simlendirmeler-ab48a03dbb3c"><em>Sahadan Temiz Kod — İsimlendirmeler | by Serkan Apul | Bimar Teknoloji Blog | Medium</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dbf13f16924d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/redis-pub-sub-ile-cache-invalidation-dbf13f16924d">Redis Pub/Sub ile Cache Invalidation Yönetimi</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kısaca Scrum]]></title>
            <link>https://medium.com/bimar-teknoloji/k%C4%B1saca-scrum-2bf6862b6451?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/2bf6862b6451</guid>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[scrum]]></category>
            <category><![CDATA[çevik-yazılım-geliştirme]]></category>
            <category><![CDATA[change-management]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 30 Dec 2024 11:00:31 GMT</pubDate>
            <atom:updated>2024-12-30T11:37:53.815Z</atom:updated>
            <content:encoded><![CDATA[<p>Sene 2025. Scrum’ı yaratan düşünce biçiminin, Scrum’ın kendisini uygulamaktan daha fazla değer kattığını anlamış durumdayım. Bununla birlikte, “Scrum eğitimi” notlarımın hala bir fark yarattığını düşünüyorum. Konuyu anlamak isteyenler için bir kaynak olabilmesi dileğiyle paylaşıyorum. Keyifli okumalar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/846/1*hX0saD_i36FSYRkmPoalvw.png" /></figure><p><strong>Manifesto for Agile Software Development : </strong><a href="http://agilemanifesto.org/"><strong>http://agilemanifesto.org/</strong></a></p><blockquote><strong>Individuals and interactions</strong> over processes and tools</blockquote><blockquote><strong>Working software</strong> over comprehensive documentation</blockquote><blockquote><strong>Customer collaboration</strong> over contract negotiation</blockquote><blockquote><strong>Responding to change</strong> over following a plan</blockquote><p><strong>Pozitif Kaygılarımız</strong></p><p>→ Backlog’um değerli mi? (Maddelerim net ve önceliklendirilmiş, iş sahipleri için değer taşıyor)</p><p>→ Backlog’umu tüketebiliyor muyum? (maddelerim bitiyor mu?)</p><p>→ Ekip mutlu mu?</p><p><strong>Scrum Framework Guide PDF : </strong><a href="http://www.scrumguides.org/download.html"><strong>http://www.scrumguides.org</strong>/download.html</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/109/1*bIORDrECylRAhvx8AMKmww.png" /><figcaption>Product Owner</figcaption></figure><blockquote><strong>Product Owner</strong></blockquote><blockquote>Ürünün değerinden / karlılığından sorumludur.</blockquote><blockquote>Müşteriye karşı sorumludur.</blockquote><blockquote>“Delivery Date” den sorumludur.</blockquote><blockquote>Developer %10 zamanını PO ya ayırır.</blockquote><blockquote>Bu sürede “backlog grooming” yani PBI ların içlerinin zenginleştirilmesi, son haline getirilmesi aktivitesi gerçekleştirilir.</blockquote><blockquote>Product Backlog unu yeni sprintler için hazır tutar.</blockquote><blockquote>Teknik borç azaltmaya yönelik altyapı — kaliteye yönelik maddeler iş değeri açısından PO ya iyi anlatılmalı ve bir PBI olarak sprint içine alınmalıdır.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/158/1*hj6o3VKy7_RbgYU1Lc9NyA.png" /><figcaption>Scrum Master</figcaption></figure><blockquote><strong>SCRUM Master</strong></blockquote><blockquote>SM = <strong>Agile Coach</strong> olarak da ifade edilebilir.</blockquote><blockquote>SCRUM konusunda ustadır. Yarım zamanlı bir iştir.</blockquote><blockquote>Ekip zamanla scrum’a alıştıkça ve ustalaştıkça SM ye ihtiyaç duymayacak bir konuma gelebilir.</blockquote><blockquote>Ekip üyelerinin mevcut işlerinde kesintiye uğramadan çalışmasını sağlamalıdır.</blockquote><blockquote>Takımın motivasyonunu devamlı yüksek tutmalıdır.</blockquote><blockquote>Takımın sprinti koşmasında, hedefe varmasını engelleyecek her türlü sorunun ortadan kaldırılmasından sorumludur.</blockquote><blockquote>Takımın refahını sağlar.</blockquote><p>Süreçler üzerinde yeni şeyler deneyelim. En fazla 1 veya 2 sprint kaybederiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OyF7fULYpMozz0ltboNwZQ.png" /></figure><p><strong>Waterfall:</strong> İnşaat ve Askeriye de geçerli olabilir. Vasıfsız isçiler eliyle yapılan işler içerir.</p><p><strong>Scrum:</strong> Inovasyon ve sanat içeren yazılım sektörü için uygundur. Ekip; eğitimli, sosyal beklentisi olan, başarılı olmaya odaklı, potansiyelinin engellenmemesi gereken bir topluluktur.</p><h3>Değişiklikleri ne kadar çabuk kabul eder ve benimsersek o kadar çabuk değer üretiriz.</h3><p><strong>PLANLAR TAŞA YAZILMAZ. </strong><br><strong>PLANA TAPILMAZ.</strong></p><p>⚠️Hata yapıldığında utanç duyulan bir sistem yaratmamak gerekir.</p><blockquote><strong>DEFINITION OF READY</strong></blockquote><blockquote>Madde yazıldı. Analizi, iş değeri belirlendi. Talebe başlamak için beklenen bir şey yok. Ekip arkadaşıma ve PO ya sorup devam edebileceğim derinlik yeterlidir.</blockquote><blockquote><strong>DEFINITON OF DONE</strong></blockquote><blockquote>Bir madde “bitti” dendiğinde <strong>bütün ekip aynı şeyi anlamalıdır. </strong><br>Örnek bir tanım: İş maddesi Build, Test, Reviev, Otomatik Testler, Sonarqube tarama, Güvenlik tarama süreçlerini geçti. Test edildi. Müşteri test sistemine çıktı. -&gt;DONE</blockquote><blockquote>BU TANIMLAR MUTLAKA YAPILMALI. TÜM PAYDAŞLAR BU TANIMDA EL SIKIŞMALI VE BU TANIM GÜNCEL TUTULMALIDIR.</blockquote><h3><strong>SCRUM SERENOMİLERİ</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/605/1*JR1Yav5Y-2sjb3y4vFCRrQ.png" /></figure><blockquote><strong>SABAH TOPLANTILARI: (FOCUS ON SPRINT GOAL!)</strong><br> Toplantıdan önce ekip üyelerinin maddelerinin son durumunu JIRA/TFS/BOARD üzerinde günceller.</blockquote><blockquote>Kalan iş BURNDOWN chart’ın güncel olmasını sağlar.</blockquote><blockquote>Hedefe koşarken önümüzdeki engeller nelerdir. Nasıl kaldırırız? Bunlar konuşulmalıdır.</blockquote><blockquote>Sen bu işle uğraşırsan sprint yetişmez. Buna bakalım.</blockquote><blockquote>Önemli olan sprintin yetişmesi önündeki engellerin kaldırılmasıdır. Sprint’e koşan faaliyetler konuşulur. <br>“Sprint için ne yaptım, ne yapacağım, kime bu yolda destek oldum” konuşulur. <br> Uzayan konu daha sonra ilgililerin kendi arasında halletmesi için kesilir. Sonra onlar devam edebilir.</blockquote><blockquote>Sabah toplantıları 15 dakikayı kesinlikle geçmemelidir.</blockquote><p>Bir nedenden dolayı beklemeye geçen kişiler, kendi gündeminden veya düşük öncelikli bir işle değil, <strong>MEVCUT SPRINT PLANINA</strong> dahil bir iş ile uğraşmalıdır. Aksi halde sprint hedefi tutmaz.</p><blockquote><strong>SPRINT PLANLAMA TOPLANTISI </strong><br>Hafta başına 2 saat planlama faaliyeti olmalıdır. Backlog’dan sıradan başlanarak o sprinte alınacak maddeler seçili</blockquote><blockquote><strong>RETROSPECTIVE TOPLANTISI </strong><br>PO bulunmaz.</blockquote><blockquote>SM ye bir KAIZEN çıkarmalıdır. Bu KAIZEN sonucu yapılacak değişiklik bir sonraki sprinte PBI olarak yansıtılabilir. SM bunu en tepeye koyabilir. Daha sonra işe yaradı mı yaramadı mı değerlendirilir.</blockquote><blockquote>Devreye alımdan sonra değişikliklerin etkisi ne oldu? Hata üretiyor muyuz? Bir sonraki sprinte neleri daha iyi yapabiliriz.</blockquote><blockquote>Bu toplantıları stressiz bir ortamda belki yemek söyleyerek, iyileştirme amaçlı yapmak lazım. Ekip kendi içinde rahatça öz eleştiri yapabilmelidir.</blockquote><blockquote>Bu toplantıda artık kimse söz almıyorsa veya toplantı artık hiç yapılmıyor ise umutlar tükenmiş her şey olduğu gibi kabul edilmiş demektir.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8jbhfA4212lEJ-HI.jpg" /></figure><p><strong>SPRINT PERFORMANSI?</strong></p><p>Velocity (ekibin planladığı sprintte çıkacak maddelerin iş değeri toplamı) değerinin artırılması performans hedefi olarak verilirse kalite düşebilir. Bununla birlikte ekip tahminleme çalışmasında otomatik olarak maddelere yüksek velocity değerleri verme eğilimine girebilir. Sonuçta çıkan iş aynı olacaktır ama velocity istatistiği bozulmuş olacaktır. Yani bu işe yaramaz. <strong>Önemli olan verimliği düşüren tüm engellerin kaldırılmasıdır.</strong></p><p>Önceki sprintte tüm çalışmaya rağmen tamamlanamayan bir USER STORY varsa, ekip planladığı kadarını bir nedenden yapamadıysa, yeni sprintte yapabileceğimiz kadar alalım. Başarılı spirintten sonra bir sonrakinde yapabileceğimiz kadar tekrar planlarız. Yapamayacağımızı bile bile fazla madde planlamanın hiçbir anlamı yoktur. Önemli olan ortadan engelleri kaldırarak, daha verimli bir şekilde sprint amacına yönelik çalışmaktır.</p><p><em>Her takımın kendi hızı vardır. Takımlar arası VELOCITY REKABETİ / karşılaştırması yanlıştır. BUG lar veya diğer olumsuz durumlar işler için kişisel sorumlu aramak ve performans sistemine yansıtmaya çalışmak takım ruhuna zarar verecektir. Cadı avına çıkılmamalıdır.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/573/1*2U2ZvbRlQteofUD0naE5sA.png" /></figure><p><strong>BİR SPRINT NASIL “BAŞARISIZ” OLUR?</strong><br>Given that each Sprint is an experiment and Scrum is an empirical process: <em>An unsuccessful Sprint is one where at the end we have not learned anything. We did not Inspect and Adapt the results for customizing the Product and Processes.</em></p><p><a href="https://www.scrum.org/resources/blog/what-failed-sprint">What is a failed Sprint?</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/645/0*d-v22JCCgBBR2NyP.png" /><figcaption>BUG Cap değeri hesaplamak kullanabileceğiniz bir formül</figcaption></figure><p><strong>BUG CAP </strong>Takımın backlog undaki / havuzundaki açık hata sayısı bir üst sınır koyuyoruz. 30 diyelim. BUG sayısı 30&#39;a ulaştığında ekip kayıt kalemi bırakıp (sprintteki “feature” geliştirimini bırakıp) hata kayıtlarını azaltıyor. Bu isteyemeyen bir durum olduğu için ekip hata sayılarını bu sınırın altımda tutma eğilimine giriyor. Hata adetlerimiz her zaman mümkün olduğunda az olmalıdır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I33F1MstXVVlvUXo.png" /></figure><p><strong>TASK/CONTEXT SWITCHING </strong><br> Kaçınmamız gereken bir durumdur. Bitirebileceğimiz kadar iş alalım. Birden fazla isin yarım yarım ilerlemesindense teker teker yapılıp bitirilmesi daha hızlı sürüyor.</p><p>→ Bir günden fazla süren TASK olmamalıdır<br> → TASK ları hep back log un tepesinden alalım. En değerli iş en önce yapılmalıdır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/318/1*9zTatARN9qBVe3aqjJR3Lg.png" /></figure><p><strong>GÜÇLÜ PIPELINE, AGILE PROJE </strong><br>Kod silebilmek yazmaktan daha zordur. Kolayca kod silebilecek güçlü bir <strong>pipeline</strong> kurmak önemlidir. Bundan kasıt şudur: unit testler, integration ve ui testlerin olmalı ki kod üzerinde değişiklik yapmaktan veya silmekten çekinmeyelim.</p><p><strong>Root Cause Analysis From Juran</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FIETtnK7gzlE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DIETtnK7gzlE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FIETtnK7gzlE%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/798bbe57be6a6841d5be474ec6e1fc55/href">https://medium.com/media/798bbe57be6a6841d5be474ec6e1fc55/href</a></iframe><p><a href="https://scaledagileframework.com/">Framework - Scaled Agile Framework</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/749/0*8bpuNYmWpwMm_XPQ.jpeg" /></figure><blockquote><strong>Acil / Araya Giren Maddeler : </strong>Bunların etiketlenmesi, daha sonra ekip ve SM tarafından etki analizinin yapılması gerekir. Süreç neden araya giren talep üretiyor. Mutlaka bir yerdeki sıkıntıya işaret edecektir. Acil işler kesinti yaratır. Bunların da iyi yönetilmesi gerekir. Bu maddeler için nöbetçi atanabilir.</blockquote><blockquote><strong>Acil Talepler için BUFFER : </strong>Sprint planında bu gibi maddeler için BUFFER zaman koymak yaygın bir yaklaşımdır. BUFFER dan kullanılmaz ise (mevcut sprintte her şey yolunda ise) yerine bir sonraki sprintten madde çekilebilir. Motivasyon yükselten bir şeydir.</blockquote><p><em>Acil istekler veya BUG lar için nöbetçi de tanımlanabilir. Ekibin toplama TASK SWITCHING kaybını azaltmış oluruz.</em></p><blockquote><strong>EMAIL HUNTING : </strong>Kim ne demişti kendimize kanıt aramak yerine arayıp konuşalım sorunu halledelim. Analiz ve test uzmanları ekibin bir parçası olabilirler. İletişimin artması beklemeleri azaltacaktır.</blockquote><h3><strong>BROOKS’S LAW</strong></h3><p>Geciken projeye adam almak işleri daha da kötüleştirir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/673/1*cEwSi40x8Sm1DzIVBZ3h7Q.png" /></figure><p><a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&#39;s law - Wikipedia</a></p><h3>CHANGE MANAGEMENT</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wvqh78jKubDZNeIh.png" /></figure><p>Organizasyonunuzda bir değişim yapacaksanız ( Scrum’ı devreye almak dahil), bu değişime sistematik olarak yaklaşmanız gerekir.</p><p><a href="https://www.prosci.com/adkar/adkar-model">The Prosci ADKAR® Model | Prosci</a></p><p><a href="https://www.prosci.com/change-management/thought-leadership-library/adkar-model-awareness"><strong>Awareness</strong></a> of the business reasons for change. Awareness is the goal/outcome of early communications related to an organizational change</p><p><a href="https://www.prosci.com/change-management/thought-leadership-library/adkar-model-desire"><strong>Desire</strong></a> to engage and participate in the change. Desire is the goal/outcome of sponsorship and resistance management</p><p><a href="https://www.prosci.com/change-management/thought-leadership-library/adkar-model-knowledge"><strong>Knowledge</strong></a> about how to change. Knowledge is the goal/outcome of training and coaching</p><p><a href="https://www.prosci.com/change-management/thought-leadership-library/adkar-model-ability"><strong>Ability</strong></a> to realize or implement the change at the required performance level. Ability is the goal/outcome of additional coaching, practice and time</p><p><a href="https://www.prosci.com/change-management/thought-leadership-library/adkar-model-reinforcement"><strong>Reinforcement</strong></a> to ensure change sticks. Reinforcement is the goal/outcome of adoption measurement, corrective action and recognition of successful change</p><h3><strong>Value Stream Mapping (VSM)</strong></h3><p>Süreç iyileştirme yöntemidir. Ürünün kodlanmasından müşteriye çıkmasına kadar olan süreç sondan başa doğru şemaya aktarılır. Bir işin toplamda beklemeler ile kadar sürdüğü, aslında asıl işin ne kadar sürdüğü karşılaştırılır. Manuel yapılan işler ve beklemelerin tespitine yarar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/430/1*nig17vXtY-Fqqbw3T2bdmA.png" /><figcaption>Bir uygulamanın devreye alım sürecindeki beklemeleri tespit etmek için yapılan bir VSM çalışmasıdır. Her kırmızı başlık (bekleme/manuel iş) için bir yorum yapmak gerekir.</figcaption></figure><p><strong>Kitap Önerileri</strong></p><ul><li><a href="https://www.amazon.co.uk/Implementing-Lean-Software-Development-Addison-Wesley/dp/0321437381">Implementing Lean Software Development: From Concept to Cash (Addison-Wesley Signature Series (Beck))</a></li><li><a href="https://www.amazon.com/Toyota-Way-Management-Principles-Manufacturer/dp/0071392319">The Toyota Way: 14 Management Principles from the World&#39;s Greatest Manufacturer</a></li></ul><p><strong>MAKİGAMİ (Roll of Paper)</strong></p><p>Bir Başka Süreç İyileştirme Yöntemidir.</p><p><a href="https://www.makigami.info/">Makigami, the Art of Systemic Process Improvement - Makigami Info</a></p><p>Bir metodun ismine karar verebildiğin anda kodun yarısını yazmış oluyorsun.</p><p><a href="https://devopsgames.com/">devopsgames</a></p><p><strong>Scrum eğitimi</strong></p><p><a href="https://scrumtrainingseries.com/">Scrum Training Series</a></p><p><strong>Resmi SCRUM Guide</strong></p><p><a href="https://scrumguides.org/download.html">Download | Scrum Guides</a></p><p><strong>Spotify Engineering Culture</strong></p><ul><li><a href="https://www.theproducthub.io/2019/10/20/agile-team-organisation-squads-chapters-tribes-and-guilds/">Agile Team Organisation: Squads, Chapters, Tribes and Guilds</a></li><li><a href="https://labs.spotify.com/2014/03/27/spotify-engineering-culture-part-1/">Spotify engineering culture (part 1) - Spotify Engineering</a></li><li><a href="https://engineering.atspotify.com/2014/09/spotify-engineering-culture-part-2/">Spotify engineering culture (part 2) - Spotify Engineering</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2bf6862b6451" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/k%C4%B1saca-scrum-2bf6862b6451">Kısaca Scrum</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[İşimiz Gücümüz Sorun Çözme (Troubleshooting)]]></title>
            <link>https://medium.com/bimar-teknoloji/i%CC%87%C5%9Fimiz-g%C3%BCc%C3%BCm%C3%BCz-sorun-%C3%A7%C3%B6zme-troubleshooting-fbe66494a5bf?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/fbe66494a5bf</guid>
            <category><![CDATA[yazılım]]></category>
            <category><![CDATA[problem-çözme]]></category>
            <category><![CDATA[türkçe]]></category>
            <category><![CDATA[i̇ş]]></category>
            <category><![CDATA[sorun]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:37:03 GMT</pubDate>
            <atom:updated>2019-11-04T19:16:13.318Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/965/1*Eh-eznNhMzsFyuvMoqFI5A.png" /></figure><p>Yazılım geliştirme uzman yardımcısından, teknik liderine, işimizin her daim bir parçası olan hata ayıklama, sorun çözme (Troubleshooting) faaliyetini gerçekleştirirken, aşağı yukarı uyguladığımız taktikler aynıdır. İşte bu taktikleri biraz derleyip toparlamaya çalıştım.</p><h4>Orijinal Sorunu Anlamak</h4><p>Sorunu <strong>sahibinden dinle</strong>, <strong>anladığına emin ol</strong>. <strong>Mümkünse kendi gözlerinle gör</strong>. Sorunu bir müşteri bildiriyor ise onu ön yargılardan uzakta ve çok iyi dinlememiz gerekir. Söylediği herhangi bir kelime bizi ipucu verebilir. Onu dinler gibi yaparken, ona nasıl cevap vereceğimizi düşünürsek veya kafamızda kod yazmaya başlarsak, müşterinin kelimeleri arasında geçen hayati ipuçlarını kaçırabiliriz.</p><p>Ayrıca, “sorunun bizim bilgisayarımızda” alınmıyor olması, “senelerdir o modülden hata gelmiyor olması” gibi mevcut sorunun çözümüne faydası olmayan gereksiz ayrıntıları müşteriye aktararak vakit kaybetmeyelim. Unutmayalım, müşterimizin vakti en az bizimki kadar değerlidir.</p><figure><a href="http://www.turkceyayin.net/"><img alt="" src="https://cdn-images-1.medium.com/max/728/1*WVJ1FMfw1QBe0aNC1mfgnA.png" /></a></figure><p>Ekip içinden veya müşteriden, “Bana şöyle çelikten, büyükçe bir çekiç lazım. Nereden bulurum” gibi, bir çözümün <strong>uygulamasına</strong> dair bir soru ve danışmanlık isteği geldiğinde, ona hemen Koçtaş’ı tarif etmeden önce, bu çekiçle ne yapmak istediğini sorun <strong>(Asıl problemi anlayın)</strong>. Belki bu sorun, o duvarda zaten olmaması gereken çiviyi tekrar çakarak değil, ufak bir pense ile oradan alınarak çözülmelidir. Asıl sorunu anlamayı başarırsanız hem bu konudaki fikrinizi söyleme şansını bulmuş, hem de yanlış bir uygulamanın akıl hocalığını yapmamış olursunuz.</p><p>Aynı şekilde; 10 MB’dan büyük EXCEL dosyasını nasıl UPLOAD ederim? CONFIG hatası veriyor dendiğinde, neden bu şekilde bir dosya UPLOAD edilecek önce anlamaya çalışın (aslında çaktırmadan sorgulayın). Belki o bilgilerin girildiği, kopyala yapıştır yapılabilen bir ekran vardır. UPLOAD işlemine gerek yoktur.</p><h4>Hata Kayıtlarını İncelemek</h4><p>Her zaman en başta hata kayıtlarını kontrol edelim. En büyük bilgi oradan gelecektir. (ELMAH/LOG4NET/LOG ANALYTICS/…) Bazen ortalık karışabilir, acilen hatayı çözeceğiz diye bu en basit adımı atlayabiliriz.</p><p>Bunun yanında elinizin altındaki diğer iz kayıtlarından (LOG) faydalanmayı unutmayalım. (Reporting Service Logs, Projenize özel İşlem/Transaction İz Kayıtları, Özel İz kayıtları (Faks sunucu, Smtp sunucu), EventLogs kayıtları da iş görecektir.)</p><h4>Her Testte Tek Bileşen Değiştirmek</h4><p>Klasöre yazma hatası alıyoruz. Hem klasöre <strong>everyone</strong> verip, hem kod içinde <strong>impersonate </strong>(Kodu başka bir kullanıcı gibi çalıştırma işlemini) yapıp tekrar denersek sorunu neyin çözdüğünü bilemeyiz. Sorun tespitini, dar kapsamdan geniş kapsama değişiklikler yaparak, yani önce kod değişikliği (BiztalkUser’i ile ilgilidir gibi), çözmedi ise <strong>everyone</strong> deneyerek yapmalıyız.</p><p><em>Einstein’ın Notu — Kod içinde veya ortamda herhangi bir değişiklik yapmadan hata senaryosunu tekrar tekrar çalıştırıp hata alıp vakit kaybetmeyelim.</em></p><h4>Sadece Çözüm İçin Gereken Değişikliği Yapmak</h4><p>Sorun, yapılan bir dizi değişiklikten (denemeden) sonra en sonunda çözüldü ise. Yapılan tüm değişiklikler (kod veya yapılandırma ayarı) geri alınıp, orijinal soruna geri dönüp, burada gerçekten sorunlu senaryo tekrar çalıştırılmalıdır. Sonra asıl çözüm olan değişikliği yapıp tekrar test edilmelidir. Bunu yapmaz isek çözüm ile alakalı olmayan değişiklikleri sisteme yansıtmış neyin nasıl çözdüğünü kendimize anlatamıyor oluruz.</p><p>Örnek: Sorun nedeniyle PRODUCTION kodunda değiştirdiğimiz her şeyi geri alıp (UNDO), sorunu tekrar edip, sadece çözen değişikliği yapıp (test edip) CI yapmalıyız.</p><h4>Hata Ortamındaki Bileşenleri Tanımlamak</h4><p>Birden fazla bileşenin olduğu karmaşık süreçlerde, bileşenlerin tamamının çalıştığına emin olalım. Sorun bu bileşenlerin birinde olabilir.</p><p>Uygulamamızdan faks gitmiyor diyelim. Sorun uygulamadan, faks Sunucusundan, faks olarak giden PDF in yazıldığı dosya sunucudan veya gönderilen faks numarasından kaynaklanıyor olabilir. İlk başta sorunu nokta atışı tespit edemediysek, hata kayıtlarından da bir ipucu elde edemediysek bu bileşenlerden her seferinde birini değiştirip deneyerek sorunu tespit etmeye çalışırız. (Başka faks numarasına gönderme, başka programdan aynı faks sunucusuna gönderme, dosya sunucu ip değiştirme gibi)</p><h4>Neyi Nasıl Çözdüğümüzün Farkında Olmak</h4><p>İnternet’ten bulunan kodlar başa bela açabilir. Aldığımız kodun ne iş yaptığını %100 anlamamız ve değerlendirmemiz gerekir (Check-In yaptığımız diğer tüm kodlar gibi).</p><p>Çözüm sunan “entry” lerin altındaki yorumları mutlaka okuyalım. Orada paylaşılan risklerin farkında olalım. Eklenen — değişen kodu mutlaka test edelim.</p><p>(<a href="https://weblog.west-wind.com/">Rick Strahl</a>’ın blog’undan da alsak) <strong>CI yaptığımız her kod bize aittir. O kodun -ne pahasına- ne iş yaptığına emin olmamız gerekir.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/791/1*Q_jpXsZrhzMxKLDy-i15sg.png" /><figcaption>Yapıştırdığımız kodun etkisi anlamak, testinin hakkıyla yapılmasını sağlamak gerekir.</figcaption></figure><h4>Çalışan Örnek İle Karşılaştırmak</h4><p>Problem yaşanan işlem başka bir ekrandan, başka bir sunucudan, başka bir “local” makinede çalışıyor ise, burada bileşenler karşılaştırılabilir. Sizin WCF servisiniz patlıyor ise, çalışan wcf servisi ile, webserver1 deki application pool çatlıyor ise, webserver2’deki apppool ile karşılaştırırız. Çalışan örneği yakalamak çok önemlidir. “Pis Hataların” çoğu bu şekilde çözülür.</p><h4>BONUS:</h4><p>Yazılım projemizdeki hatanın çözümü uzayacak gibiyse, deneysel işler yapacağımız bir sorun ile uğraşıyorsak, hatayı alabileceğimiz en sade proje solution’unu üzerinden çalışmak gerekir. (Tüm projelerin ekli olduğu .sln dosyasını açmak yerine)</p><p>Hele ki (Telerik, Dynatrace, Microsoft gibi) bir firmadan “Ticket” açma gibi süreçler işin içine girecek ise, en güzeli <strong>sadece hatayı alacak kadar bileşen ve kodun olduğu örnek bir projede hazırlamaktır</strong>. Bu genelde düşünülenden daha az zaman alır. Sorun bu projede çözüldükten sonra asıl problemli ortam düzeltilebilir.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fbe66494a5bf" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/i%CC%87%C5%9Fimiz-g%C3%BCc%C3%BCm%C3%BCz-sorun-%C3%A7%C3%B6zme-troubleshooting-fbe66494a5bf">İşimiz Gücümüz Sorun Çözme (Troubleshooting)</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kod Review Kafası]]></title>
            <link>https://medium.com/bimar-teknoloji/kod-review-kafas%C4%B1-417dd42f0fc6?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/417dd42f0fc6</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[code-review]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:35:24 GMT</pubDate>
            <atom:updated>2018-11-28T23:16:08.593Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/397/1*q0GB9BQwkQATt1TuUco1Yg.png" /></figure><p>Kod okumanın da bir metodolojisi var mıdır? En azından benim için bir tane oluştu. İşte, Pull Request / Code Review Request önüme geldiğinde kodu okurken, cevap aradığım sorular şunlar;</p><h3>Yapılan değişikliğin karşılaması gereken <strong>asıl ihtiyaç</strong> nedir?</h3><p>Yeni özellik, “user story”, “task” veya talepte istenen nedir? Tek tek kod parçalarına bakarken bu parçaların toplamda neye hizmet ettiği aklımızdan çıkmaması gerekir. Ancak bu şekilde her sınıf içinde yapılacak değişikliklerin alternatifi yanında, resmin tümüne dair, yani toplamda işin daha etkin nasıl yapılabileceğine yönelik bir fikir üretebiliriz.</p><p>⚠️ İşlevsel testi üzerimize almıyoruz. Bununla birlikte, yeni bir raporu sisteme eklediğini iddia eden bir isteğin “pull request’i” içinde en azından ilgili raporun olmazsa olmaz tanımlarının yapıldığını görmeliyiz.</p><h3>Kopyalanan bir mantık-bilgi var mı?</h3><p>Çok genel bir iş sıfırdan yazıldıysa / veya olması gereken modülden farklı bir yerde yazıldıysa şüphelenmek gerekir. Genel bir işin tekrar yapıldığından veya kopya kod olduğundan şüpheleniyor isek, eklenen kısımdan bir parça (özel bir parça, kullanılmış sabit gibi filtreye eklenen bir alanın filtreye ekleme kodu gibi ) alıp, “solution” içinde arayabiliriz. Birebir aynı kod parçasına rastlama olasılığınız yüksektir. Mevcudu kopyalamanın yanında, toplamda talep için çıkılan kod içinde kendini tekrar eden kısımlar var mı?</p><p><strong>Aynı satırlar birden fazla sınıfa aynı şekilde eklenmiş ise</strong> muhtemel bir “refactor” ihtiyacı vardır.</p><p>❗Bilerek ve isteyerek blok olarak kodun klonlanması ciddiyetle ele alınması gereken uygunsuz bir durumdur. Mutlaka irdelenmelidir ve arkasındaki neden ortadan kaldırılmalıdır.</p><h3>Yazılan kod içinde bir varsayım var mı?</h3><p>Özellikle birim ve entegrasyon testleri zayıf projelerde burası tam bir madendir. (Az sonra örnek vereceğim) belli başlı varsayımlar “developer” tarafından (kendim dahil:) “fütursuzca” kodlanabilir. Kod review bunları durdurmak için bir fırsattır. İşin özünde <strong>işlem yapan birimler kendini garantiye alıyor mu</strong> buna dikkat edilmelidir.</p><p>❓Onayla işlemi yapan metot içinde, buraya gelen kayıt zaten “onaya hazır” statüsündedir diye bir varsayım var mı? Yoksa kaydın statüsünün bu işlem için uygun olduğu işlemin başında doğrulanmış mı?</p><p>❓Metoda liste geçilmişse bu liste zaten dolu gelmiştir gibi bir varsayım var mı? (En sık yapılan varsayımlardan biridir. Bir sistemi çalışmaz hale getirecek örneğe rastlamışlığım vardır. Sonra “müdürler” aramaya başlar:)</p><p>❓ “upload” edilen dosyanın boyutu ile ilgili bir doğrulama var mı yoksa kullanıcının “sistem dosyaları arşivini” zaten buraya yüklemeyeceği mi varsayılıyor. NOT: Kullanıcı bu eylemi istemeden de gerçekleştirebilir. Yazacağımız doğrulama metotları bunların da önüne geçecektir.</p><h3>Yazılan kod içinde &lt;<strong>kaldırılan bir çit&gt;</strong> var mı?</h3><p>Silinen kodlara, değişen “IF-ELSE’lere, filtreleme ve relation ilişkilerindeki değişikliklere özellikle dikkat edilmelidir. Bunlar mevcut veriyi ve akışı değiştiren müdahalelerdir.</p><p><strong>Çit kaldırmak </strong>(önceden daha özel bir kapsamda çalışan bir kodu daha genel için çalışan bir kod haline getirmek), çit koymaktan (kısıt getirmekten) daha tehlikelidir. Bulması gereken kaydı bulamaz ise iş kesilir hata kaydı açılır. Ama çiti kaldırır ve bulmaması gereken kaydı bulup işlemesine neden olursak bundan hiç bir zaman haberimiz dahi olmayabilir. Bir çit kaldırıldı ise bunun zamanında ne amaçla konulduğu anlaşılmış, artık gerek olmadığından emin olmak gerekir. Biz koda bakınca emin olamıyor isek mutlaka sorgulamalıyız.</p><h3>Atama ve kontrollerin muhatapları uyumlu mu?</h3><p>Bu tip hataların bulunmasını beklediğimiz asıl yer kod review değildir aslında. Bununla birlikte kodu okurken (bir yandan kafamızda çalıştırırken) Atamalarda ve kontrollerde, sağ tarafta oluşturulan ifade ve değer ile atama yapılan / kontrol edilen sol taraf uyuma bakmamız çok efor sarf ettirmez, hatta belli bir tecrübeden sonra bu uyumsuzlar hemen göze batar. Yakalarsak iyidir. Yoksa zaten testlerde bu tip hataların yakalanması beklenir.</p><p>❓ Listeleme işleminde filtre oluştururken kullanıcının TC Kimlik Nu. bilgisine, ekrandaki vergi numarası alanından mı atama yapılmış?</p><p>❓ Mantıksal olarak, çağrılan metot, atama yaptığımız alan ile uygun mu? entitiy.FaturaToplamTutar=BolgeselVergiHesapla();</p><h3>Build’e etki etmeyen maddi ve mantıksal bir hata yapılmış mı?</h3><p>Yapılan bir dizi değişiklikle çelişen, genel desenin dışında kalan bir değişiklik var mı? Böyle bir durumda mutlaka kod kontrol ettirilmelidir.</p><p>❓ Bir hata maddesi üzerine bir dizi metot içinde kur bilgilerinin TL’ye dönüşümü ile ilgili değişiklikler yapılırken sadece tek bir metotta kurun USD olmasını varsayan bir kısım bırakılmış. Burada hemen “developer”a bilgi vermek, her şey kontrol altında mı diye sormak gerekir.</p><h3>Standart dışı bir kullanım var mı?</h3><p>❓Yayınlanmış olan genel veya projeye özel gözden geçirme kontrol listesine aykırı bir kullanım var mı?</p><h3>Bu işi daha anlaşılır (sade) bir şekilde yapmak mümkün mü?</h3><p>❓Karmaşık yapılar yerine daha basit düşünülüp, daha basit, okuyanın rahat anlayıp müdahale yapacağı şekilde yazmanın bir yolu (modelleme imkanı) var mı?</p><p>Biraz karmaşık algoritma içeren sorunlar, genelde nispeten daha az tecrübeli veya bazen mevcut framework’e tam hakim olmayan yazılımcılar tarafından akla gelen ilk şekliyle, düz mantık ile (muhtemelen deli gibi kaynak tüketecek şekilde) koda dökülerek çözülebilir. Böyle durumlarda gerekirse o kısmı olması gerektiği gibi daha performanslı ve zarif bir şekilde yeniden gerekirse beraber yazmak gerekebilir.</p><h3>Bu işi daha az kaynak ile daha hızlı yapmanın bir yolu var mı?</h3><p>Yazılım geliştirme faaliyetinin belki de her aşamasında sorulacak soru budur. Aynı IF / Metot / Sınıf daha az veri çekerek, daha az veri tabanına giderek, daha az kod yazarak yeniden düzenlenebilir mi düşünmemiz gerekir.</p><p>Bu konuda yine teknik kabiliyetler öne çıkmaktadır. Hangi framework’te çalışılıyor ise örneğin veri çekmek için değişik senaryolarda en etkili yöntemlerin ekibe aktarıldığından emin olunması kritiktir.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=417dd42f0fc6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/kod-review-kafas%C4%B1-417dd42f0fc6">Kod Review Kafası</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Senin bilgisayarında çalışıyor çünkü …]]></title>
            <link>https://medium.com/bimar-teknoloji/senin-bilgisayar%C4%B1nda-%C3%A7al%C4%B1%C5%9F%C4%B1yor-%C3%A7%C3%BCnk%C3%BC-64e4e84a500a?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/64e4e84a500a</guid>
            <category><![CDATA[troubleshooting]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[problem-solving]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:35:10 GMT</pubDate>
            <atom:updated>2018-12-10T20:46:15.106Z</atom:updated>
            <content:encoded><![CDATA[<h3>Senin bilgisayarında çalışıyor çünkü …</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/531/1*uR_0VbtIsO6Nk60JKfr5DQ.png" /><figcaption>Bir BUG’ı hiç yaşanmamış saymak ile tekrar edilemediği için kapatmak arasında neredeyse fark yoktur.</figcaption></figure><p>Senin bilgisayarında çalışıyor çünkü …</p><p>Senin kullanıcın “admin” olarak tanımlı, her sunucuya girer-çıkar yazar-silersin, kullanıcının standart tanımı belki “read-only” bile değil.</p><p>Sen uygulamaya tüm yamaları yüklenmiş Windows 10&#39;dan, kullanıcı Windows 2008 R2 TS üzerinden erişiyor.</p><p>Sen hatayı o “bug” kaydına sıra geldiğinde, sana uygun zamanda tekrar etmeye çalışıyorsun, hata ise sistemi kilitleyen başka bir sorgunun çalıştığı anlarda meydana geliyor.</p><p>Sen Chrome kullanıyorsun, hemen derleyip sayfayı ekrana basıyor, kullanıcıda artık “sistem destek” zamanında ne kurdu ve hangi versiyonda bıraktıysa o var.</p><p>Sen bilgisayarını sunucuyla aynı switch’e bağlayabilecek kadar sistem odasına yakınsın, kullanıcın Senegal Telekom — VPN — Türkiye artık nereden kaç hop ile geliyorsa o kadar uzakta.</p><p>Yani aslında, sen derleyip, “Check-In” yaptığın şeyde hata ararken, kullanıcı bunu mümkün kılan birçok bileşene bağlı olan, ekranında o anda çalışması gereken uygulamaya yansıyan problemden bahsediyor.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=64e4e84a500a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/senin-bilgisayar%C4%B1nda-%C3%A7al%C4%B1%C5%9F%C4%B1yor-%C3%A7%C3%BCnk%C3%BC-64e4e84a500a">Senin bilgisayarında çalışıyor çünkü …</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kaliteli Yazılımın Nitelikleri & Temiz Kod+]]></title>
            <link>https://medium.com/bimar-teknoloji/kaliteli-yaz%C4%B1l%C4%B1m%C4%B1n-nitelikleri-temiz-kod-c3c4cf01b451?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/c3c4cf01b451</guid>
            <category><![CDATA[yazilim-gelistirme]]></category>
            <category><![CDATA[quality]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[temiz-kod]]></category>
            <category><![CDATA[quality-assurance]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:33:50 GMT</pubDate>
            <atom:updated>2023-09-11T11:09:13.418Z</atom:updated>
            <content:encoded><![CDATA[<h3>Kaliteli Yazılımın Nitelikleri &amp; Temiz Kod</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RFrMmAlhlcyhB00z_CQGbA.png" /></figure><p>Uygulamamızın derlenmesi ve istenilen işi <strong>bir şekilde yapmas</strong>ı üniversite dönem ödevimiz için yeterli olabilir. Fakat <strong>iş kurumsal bir yazılım</strong> üretmeye gelince <strong>bundan fazlası</strong> gerekir.</p><p>Yazılım geliştirme faaliyeti sırasında aldığımız bazı kararlar yazılımın kalitesine olumlu katkı sağlarken, kimisi de buna engel olur.</p><p>Yazılım kalitesi dediğimiz şey aslında hangi niteliklerdir, bizim hangi faaliyetlerimiz bu niteliklere nasıl etki eder, işte bu yazıda bunlardan bahsetmek istiyorum.</p><p><strong>Bir yazılım ondan istenen işi doğru olarak yapacak işlevlere sahiptir. Bununla birlikte …</strong></p><h3><strong>�</strong>�KALİTELİ YAZILIM GÜVENLİDİR.</h3><blockquote><em>🚫Yetkim olmayan işlemi çalıştıramam.</em></blockquote><blockquote><em>🚫Yetkim olmayan bilgiyi göremem.</em></blockquote><blockquote><em>🛡️Bilgi veya iletişimim ifşa olmaz.</em></blockquote><blockquote><em>🛡️Uygulama ve sistem zayıflık (zafiyet) içermez.</em></blockquote><h4>Kaçınalım❗</h4><p>❌ <strong>İhtiyaç olandan daha geniş yetki tanımı</strong> <em>(sadece okuma işi olan bir sürece / kullanıcıya admin yetkisi vermek, “everyone” erişim yetkisi verilen klasör vb.)</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/643/1*iKW2yduKK3Zw6H12vAPE6g.png" /><figcaption>Bir kaynağa geniş bir grup için erişim vermek her zaman sorgulanması gereken bir eylemdir.</figcaption></figure><p>O an için uygulamamızın “klasöre yazma sorununu” bu şekilde çözerken sonra başımıza gelebilecekleri tahmin etmemiz zor olabilir. Bknz.: <a href="https://en.wikipedia.org/wiki/CryptoLocker">https://en.wikipedia.org/wiki/CryptoLocker</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*4K8SsxX3HWXC_m0TPONMpQ.png" /><figcaption>Sene 2013. CyrptoLocker virüsü, everyone yetkisi ile sorunlarını çözen kimi IT’lere acı bir ders verdi.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Rb1R1TVQuO3C98tdgdsLMw.png" /><figcaption>Birine bir anahtar verirken o anahtarın hangi kapıları açabileceğini iyi değerlendirin.</figcaption></figure><blockquote>Bir <strong>token</strong> yaratıyorsanız, o token ile yapılacak <strong>işin gerektirdiği kadar yetkiyi — işin gerektirdiği süreyle- verdiğinize emin olunuz</strong>. API’den okuma sadece okuma yapacaksanız, okuma yetkisi vermek yeterlidir. Bu tip anahtarların kötü niyetli kişilerin eline geçtiğinde hangi işlemleri yapabileceğini bildiğinize emin olun.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/678/1*CCcfOFYHBW8sQxsqT1AsTQ.png" /><figcaption>Şimdilik deneme için Full Access vereyim demeyin. Unutabilirsiniz.En az ayrıcalık ilkesine uyulması, yetkisiz erişim, kötüye kullanım veya kazara hasarı en aza indirerek genel güvenliği artırır.</figcaption></figure><p>💡 Sadece yetkiyi verirken değil, isterken de bu prensibi uygulayın. Bir sisteme bağlanmanız gerekiyor diyelim. Sadece okuma yapacaksanız, readonly yetkisi olan bir kullanıcı adı şifresi isteyin veya TABLO yerine bir VIEW’e yetki vermelerini isteyin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/747/1*UEz6nEsKjUT3SGJ-Ei69nA.png" /><figcaption>En az ayrıcalık ilkesine uyulması, yetkisiz erişim, kötüye kullanım veya kazara hasarı en aza indirerek genel güvenliği artırır.</figcaption></figure><blockquote><em>❌ kullanıcı adı, şifre gibi </em><strong><em>hassas bilgilerin koda gömülmesi</em></strong><em>: Bu bilgiler kaynak koddan çıkartılabilir ve istismar edilebilir. Koda gömülü şifre sistemde değiştiğinde ilgili işlev çalışmaz hale gelir. Günceleyip devreye almak için kesinti yapmak gerekir.</em></blockquote><p><a href="https://rules.sonarsource.com/java/RSPEC-2068/">Java static code analysis: Hard-coded passwords are security-sensitive</a></p><blockquote><em>❌</em> <em>Kimlik, pasaport veya diğer hassas bilgilerin, </em><strong><em>onay alınmadan sisteme kayıt edilmesi</em></strong><em>, bunların gizleme ve yetkilendirme işlemlerinin yapılmaması. Bknz.: </em><a href="https://www.kvkk.gov.tr/Icerik/4185/6698-Sayili-Kisisel-Verilerin-Korunmasi-Kanununun-Amaci-ve-Kapsami"><em>https://www.kvkk.gov.tr/Icerik/4185/6698-Sayili-Kisisel-Verilerin-Korunmasi-Kanununun-Amaci-ve-Kapsami</em></a></blockquote><h4>Sürdürelim👍</h4><p>🔏 <strong>İşlemlerde </strong>şirket, bölge, ofis, kullanıcı, rol gibi tanımlar üzerinde <strong>yetki kontrolü yapılır</strong>. Bir gruba tanımlanmış işlemi diğer grup çalıştıramaz, onun verisini göremez.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/283/1*HtCUxaerUJI_E0E_Z0X3jQ.png" /><figcaption>Bir ekran veya rapor hazırlarken bu ekran veya rapora kimler erişecek sorusunu sormak gerekir.</figcaption></figure><p>🔏 Bir bilgi özellikle istenmedikçe hiç bir çıktıda (dosya, rapor, ekranda) yer almaz. <em>Çıktılar testler esnasında bu kapsamda kontrol edilmelidir. Bu bilgi neden burada diye her zaman sorgulamak gerekir.</em></p><p>🔏 Yetki — Güvenlik kontrolü yapan bir metodun <strong>varsayılan dönüş değeri “false/yetki yok/görünmesin”</strong> dir. Önce bu kod yazılır, sonra yetkili olduğu senaryolarda “true” döndüren kodlar yazılır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/559/1*2kIp2DajWA1L2iE4pI4gzA.png" /><figcaption>Varsayılan olarak yetkisi yok diye düşünülmelidir. Yetkili olduğu durumlar özellikle kodlanır.</figcaption></figure><p>🔏 Kullanıcı şifresini karmaşıklığı ayarlamak, periyodik olarak değiştirmeye zorlamak ve bunun gibi bir çok kritik konuyu elle kodlamak gerine bu sorumlukları güvenli alternatiflere devredebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/1*vuU0Vvs-eWbfM4CSy-2UWA.png" /><figcaption>Kullanıcı kayıt işlemini güvenlik alternatiflere devrederek, kullanıcın uygulamayı daha çabuk kullanmaya başlamasını da sağlarız.</figcaption></figure><p>🔏 Canlı sistem erişim bilgileri, sadece sorumlusunun erişebileceği modern yöntemler kullanılarak saklanır. (yetkili kaynakta bir yapılandırma dosyası, “Key Management”, “Key Vault” vb. hizmetler )</p><p>🔏 Yazılım kalitesi başlığı altında konuştuğumuz “Yazılım Güvenliği” pratikte kendi başına değerlendirilen bir unsurdur. Yazılım ekiplerinin bu konuda <strong>eksiklerinin tamamlanması</strong>, her aşamada <strong>uluslararası güvenlik standartlarının uygulanması</strong>, kod gözden geçirme, statik kod tarama gibi faaliyetlerinin <strong>güvenlik başlıklarının öncelikli olarak ele alınması</strong> gerekir.</p><blockquote><strong><em>🛑</em> </strong><em>Yazılım güvenliği konusunda hem </em><strong><em>prensip </em></strong><em>hem </em><strong><em>uygulama</em></strong><em> olarak ortaya konmuştur </em><strong><em>standartlar</em></strong><em> vardır. </em><strong><em>OWASP</em></strong><em> bunlardan en iyi bilinenidir. Bu konuda rehber olacak </em><strong><em>en önemli 2 kaynağı</em></strong><em> aşağıda paylaşıyorum.</em></blockquote><ul><li><a href="https://owasp.org/www-project-top-ten/">OWASP Top Ten Web Application Security Risks | OWASP Foundation</a></li><li><a href="https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html">AJAX Security - OWASP Cheat Sheet Series</a></li></ul><h3>🚲KALİTELİ YAZILIM VERİMLİDİR.</h3><blockquote><em>🚀 Yüksek performans gösterir.</em></blockquote><blockquote><em>🔋 Az kaynak tüketir.</em></blockquote><blockquote><em>⬇️ Response Time</em></blockquote><blockquote><em>⬇️ I/O, Bellek, CPU, Ağ Trafiği</em></blockquote><h4>Kaçınalım❗</h4><p>💣 Döngü içinde açıkça veri tabanı çağrısı yapmak (veya arka planda bu çağırımı yapan kod yazmak)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*J7rAhCj2nOmm9G0oTiWDrQ.png" /><figcaption>Yazdığınız kodun döngü içinde olup olmamasına ve ürettiği sorguya çok dikkat etmelisiniz.</figcaption></figure><p>❌ Döngü İçinde string birleştirmek</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tPH8W8sVSiU0ZL3g4tmzww.png" /><figcaption>String.Contat ile + işlemi aynıdır. İkisi de sorun yaratır. Burada StringBuilder kullanılmaldır.</figcaption></figure><p>❌ Sorgularda <strong>gereksiz fonksiyon</strong> kullanımları. (CAST, DISTINCT, UPPER, REPLACE, SUBSTRING vb.)</p><p>❌ <strong>SELECT * FROM</strong> şeklinde sorgu çalıştırmak veya bu sorguyu oluşturan kod yazmak. <em>( Hali hazırda “hazır” olan View’lere bir alan da kendimiz ekleyip içinden çıkılamayan performans ve refactor sorunları yaratmak)</em></p><h4>Sürdürelim👍</h4><p>✔ Gerektiği kadar ( ihtiyacımız olan kadar) veriyi çekelim.</p><p>✔ Elimizde zaten olan veriyi çekmeyiz. <strong>Her zaman ön-belleklemeyi değerlendirmeliyiz.</strong> ( I❤CACHE) 🌟</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/786/1*NmDK3gPbyb8u_i7WSLNQBg.png" /><figcaption>Örnek bir ön-bellekleme ( caching ) uygulaması. Ufak bir ekleme ile 3X performans elde edilmiş.</figcaption></figure><p>✔ Önce Veri Tabanı Çağrısından Bağımsız Kontrolleri Yapmak</p><blockquote>VT çağırımı yapmadan önce, eleyebileceğimiz senaryoları önce kontrol etmek, gereksiz çağırımlara engel olacaktır.</blockquote><blockquote>Örneğin, bir <strong>IF</strong> kontrolünün operatörleri arasında, hali hazırda değeri atanmış bir tane var ise, önce sadece onu içeren bir IF yazarak, veya o ifadeyi IF kontrolü içinde sol tarafa alarak gereksiz veri tabanı sorgusundan kaçınmış oluruz (ifadeler soldan sağa doğru işlenir). Şöyle ki;</blockquote><blockquote>IF ( TablodaKayitVarMi() || tutar==0) yerine</blockquote><blockquote>IF ( <strong>tutar==0 || </strong>TablodaKayitVarMi()) şeklinde yazarsak</blockquote><blockquote>Metoda vs. gitmeyen zaten değerini almış <strong>tutar==0 </strong>kontrolünü <strong>OR ifadesinin soluna alırsak</strong>, tutar==0 olan tüm senaryolarda veri tabanı çağırısı veya başka işlemler yapan TablodaKayitVarMi() metodunu boşuna çalıştırmamış oluruz.</blockquote><p>✔ Sadece <strong>ihtiyacı karşılayacak kadar</strong> kaynak yaratırız. (Örneğin: LOG yazma ihtiyacı için .doc❌ uzantılı dosya kullanılmaz. Bu iş için çok daha az kaynak tüketen .txt✔ uzantılı dosya yeterlidir.)</p><p>✔ Kaynaklar (connection, stream, vb.)<strong> işi biter bitmez iade edilir. </strong>(kapatılır, using{} kapsamında kullanılır, “dispose” edilir vb.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/456/1*eK6OXrP8Y3t6B3WfOk_hVw.png" /><figcaption>Connection açık bırakılmaz.</figcaption></figure><p>✔ Uygulama performansı izlenir ve iyileştirilir.( App.Mon. Tools, Veri tabanı logları, IIS logları)</p><p>✔ Performans ve kapasite sorunlarında çözüm için donanım kaynak artışına değil, ihtiyaç artışının arkasındaki asıl sorunu çözmeye odaklanılır.</p><p>✔ Çıktıların saklanmasını isteyen taleplerde mutlaka saklama süresini (“retention”) sorgulanır. Erişime en az ihtiyaç duyulan dosya en yavaş (en ucuz) kaynakta saklanır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*cnUaD52rrm_rCsNPmQavlw.png" /><figcaption>Operasyonel olmayan, sık değişmeyen veriler için mutlaka ön-bellekleme (caching) düşünülmelidir.</figcaption></figure><h3><strong>📐</strong>KALİTELİ YAZILIM <strong>GÜVENİLİRDİR.</strong></h3><blockquote><em>⚙️Kesinti yaşanmaz.</em></blockquote><blockquote><em>🐞Hata üretmez. (Bu biraz iddialı oldu. Ürünün bilinen risklerini azalttığımız için hata üretmemesi beklenir diyelim:) .</em></blockquote><h4>Kaçınalım ❗</h4><p>❌ “Single Point Of Failure” tasarımlar ( 3 web sunucu var iyi güzel ama tek Authn. sunucun çökerse uygulamalara girilmiyor)</p><p>❌ Bire bir aynı olması gereken sistemler arasındaki ( bir uygulamanın test ve canlı sunucusu arasındaki veya aynı uygulamanın tüm canlı sunucuları arasındaki) yapılandırma ( patch, kurulum vs. ) ayarları farklılıkları.</p><p>❌ Eksik UC,CC, İş Kuralı doğrulaması (Validation)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fyv7Cc6Vzo2kdvAboeBT8w.png" /><figcaption>Veriyi veri tabanından hata olarak dönmeden önce doğrulama (validation) kodu yazarak kontrol etmeliyiz.</figcaption></figure><p>❌ Static Değişkenler : ( Birden fazla “instance’in” sanki sadece kendisine aitmiş gibi ortak bir değişkeni güncellemesi veya oradan okuma yapması)</p><p>💣 Eksik NULL Kontrolü</p><blockquote>“Nullable” nesneler ile iş yaparken, yazdığınız yerde o nesne “null” geldiğinde uygulamanızın nasıl davranması gerektiğini bilmelisiniz ve o senaryoyu kapsayacak (destekleyecek) şekilde kodunuzu yazmalısınız.</blockquote><p>💣 Eksik “Count”, “Length” Kontrolü</p><blockquote>Bir listenin, referans ettiğimiz elemanının o listede olduğundan emin olmamız, kontrol etmemiz gerekir. En yaygın yapılan hata, boş bir listenin ilk elemanını okumaya çalışmaktır. (collectionX[0].Ad)</blockquote><p>💣 Exception yutmak</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/485/1*1S8mdlg-DXKeQz-OsnmeeA.png" /><figcaption>Bu koda bakım yapacak kişiye bundan başka yapılabilecek çok az kötülük vardır.</figcaption></figure><p>❌ Doğrulamak yerine, varsayarak kod yazmak (liste dolu gelir, 10’dan fazla seçmez, yetkisi olmayan şirketi seçip buraya gelemez, bu işlem exception almaz, dosyayı diske her durumda yazar varsayımları vb. )</p><p>❌ TR/EN, date time format, UTC, regional settings farklılıklarının göz ardı edilmesi</p><p>❌ Kodlama ve testlerde sadece mutlu senaryoya odaklanılması, uç senaryoların göz ardı edilmesi ( seçim yapmazsam, birden fazla seçim yaparsam, girmeme izin verilen maksimum karakter sayısını kullanırsam ne olur bakış açısıyla kodlamak / test etmek gerekir)</p><h4>Sürdürelim👍</h4><p>✔ Sürekli devreye alım ve kısa kesinti süresi</p><p>✔ Load Balancer / Web Application Firewall / Clustering yapıları</p><p>✔ Kod gözden geçirme faaliyeti</p><p><a href="https://serkanapul.medium.com/kod-review-kafas%C4%B1-417dd42f0fc6">Kod Review Kafası</a></p><p>✔ Manuel Testler, Onay testleri</p><p>✔ Test Otomasyonlar (Unit Testler, Automated UI testler)</p><h3>🛠️KALİTELİ YAZILIMIN BAKIMI KOLAYDIR.</h3><blockquote><em>🔌Değişiklikler rahat yansıtılır.</em></blockquote><blockquote><em>🔧Kod Bakımı / Refactor kolay yapılır.</em></blockquote><blockquote><em>🕵️Hata ayıklamak kolaydır.</em></blockquote><h4>Kaçınalım❗</h4><p>❌ Tekrar Eden Kod blokları</p><blockquote><strong>Kopyala-Yapıştır;</strong> Daha önce benzer veya aynı işi yapan bir kod parçası bulunup, yeni yazılan yere aynen yapıştırır.</blockquote><blockquote>Yeni yazılmak istenen işlev, hali hazırda <strong>proje içinde olması gereken sınıfların içinde bulunmasına rağmen</strong>, proje yapısına hakim olunmadığı veya daha kötüsü özensizlik nedeniyle, oradan çağırmak yerine, kullanıldığı yerde tekrar yazılır.</blockquote><blockquote>Bir işlev daha önce <strong>ayrı bir metot olarak yazılmadığı</strong> için, kod içerisinde farklı parametreler için <strong>aynı kod blokları tekrar yazılır</strong>. Yapılması gereken şey önce parametre ile farklı iki kullanımı destekleyecek şekilde bir metot yazıp, hem eski kullanımı, hem yeni yazacağımız kodu bu metodu çağıracak şekilde düzenlemektir.</blockquote><p><em>Örneğin Ekle ve Güncelle işlemleri içinde tekrar eden doğrulama ( validation ) kodlarını, validation adında bir sınıf altında tekleştirip, 2 işlem içinden orayı kullanmak iyi bir pratiktir)</em></p><p>❌ Sihirli Sayılar ( IF kullaniciCinsiyet <strong>== 1</strong>)</p><p>👍( IF kullaniciCinsiyet<strong>== Cinsiyet</strong>.Erkek)</p><p>❌ Çarşaf ( Büyük ) Metotlar : <em>Bir metot ne kadar büyük ise, orada tekrar eden kısımların veya metodun asıl işlevini değil de yan işlevleri yapan kod parçalarının olma olasılığı yüksektir. Böyle metotlarda iyileştirme yapılması ve işlevlerin metotlara ayrılması gerekir. Bir ekran boyunu geçen bir metot, uzun olarak ifade edilebilir.</em></p><blockquote>Bir işi yapan tek bir metot olmalıdır.</blockquote><blockquote>Bir metot sadece bir iş yapmalıdır.</blockquote><blockquote>Yeni bir işlev veya değişiklik, sadece bir parça kodu (veya tanımı), değiştirerek (veya ekleyerek) koda yansıtılabilmelidir</blockquote><p>❌ Bağımlı İşlemler ( uygulamada bir işleyişi değiştirmek için 2 veya daha fazla sınıfta değişiklik yapmak zorunda olmak)</p><p>❌ Koda gömülü “sabitler” (aslında değişebilecek bilgiler)</p><p>Kod içerisinde string bir bilgiyi, sabit olarak bir atama veya kontrolün içinde kullanmamız gerekir. Bu bilgiler çoklu dil desteğini sağlayabilmek ve daha kolay bakım yapabilmek adına ilgili “resource” kullanılarak getirilmelidir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*e64yJySHy1e7tDbQqufrdg.png" /><figcaption>Resource kullanmak olası bir değişikliğin kolay yapılmasını sağlar.</figcaption></figure><p>❌ /* yorum satırı yapılmış kodlar; */</p><blockquote>Kodlar yorum satırı haline getirilmek yerine doğrudan silinmelidir. Bu kodlar daha sonra o kodu okuyan kişiyi şüpheye düşürüp kafasını karıştırabilir. (Geri alınacak mı? Neden silinmedi? Bir sebebi varsa öğrenmeliyim kim yorum satırı yapmış? vs.)</blockquote><blockquote>Silinen kodlara, ne zaman, hangi istek nedeniyle silindiği bilgisine kaynak kontrol (TFS, GIT) araçlarından daha sonra zaten ulaşabiliriz.</blockquote><blockquote>Kod içerinde değişiklik yapan kullanıcı, değişiklik numarası gibi gereksiz bilgiler yorum satırı olarak girilmemelidir. ( /* task-1232 *Apul */ gibi)</blockquote><blockquote>Kodun içinde yorum gerektirmeyecek, <strong>yapılan işin çok net olduğu</strong> kodlar için yorum satırı yazılmamalıdır. (//şimdi kayıt ediliyor, //karşılaştırma gibi)</blockquote><blockquote>//****************** gibi kodun okunmasını zorlaştıran yorum satırı yazılmaz. (flowerbox).</blockquote><blockquote><strong>Yorum Yalan Söyleyebilir, Kod Asla : </strong>Bir metot mümkün olduğunca, <strong>yorum satırı gerektirmeyecek sadelikte</strong> yazılması, isimlendirmelerin de aynı sadelikte ve anlaşılır şekilde yapılmış olması gerekir. Kodun kendisi yorum satırı gibi net olmalıdır. Yazılan metodu anlatmak için fazlaca yorum satırı gerektiriyor ise, o metoda bir refactor yapılması (iyileştirmesi veya yeniden daha sade/basit yazılması) değerlendirilmelidir.</blockquote><blockquote>Metodun başına gelip /// yazığında, “Summary” girişi için gerekli TAG lar otomatik olarak açılır. Metot ne iş yaptığı bir bakışta çok net anlaşılacak ( IkiSayiTopla(long A long B) ) gibi bir metottan bahsetmediğimiz sürece bu “Summary” yorumları mutlaka yazılmalıdır.</blockquote><p>🚮 <strong>Çöpler</strong> (<strong>kullanılmayan değişken, metot, sınıf, proje, klasör, site, sunucu, dns tanımı</strong> vb.) çöp oldukları (veya öyle oldukları sonradan anlaşıldığı) anda <strong>silinmelidir</strong>. Çöpler nasıl koku yapar, sinek çeker, ayağa takılır. Yazılımda çöp, dosya boyutlarını artırır. Devreye alımı uzatır. Değişiklik ve iyileştirme (refactor) süresini artırır. İşi gücü bırakır, bu kullanılıyor mu niye burada diye şirket içinde dört dönersiniz.</p><h4>Sürdürelim👍</h4><p>✔ Makinenin değil, bir insanın anlayacağı açıklıkta sade kod yazmak.</p><p>✔ Constants, Enums kullanılır ( IF kullaniciCinsiyet<strong>== Cinsiyet</strong>.Erkek)</p><p>✔ İsimlendirmeler <strong>sade</strong>, <strong>alakalı</strong>, <strong>anlaşılır</strong> ve ilgili <strong>proje standartlarına</strong> uygun olmalı. ( <strong>bool</strong> <strong>is</strong>Successful✔, <strong>bool</strong> <strong>is</strong>Empty✔, <strong>bool</strong> updated❌)</p><p><a href="https://serkanapul.medium.com/sahadan-temiz-kod-i%CC%87simlendirmeler-ab48a03dbb3c">Sahadan Temiz Kod - İsimlendirmeler</a></p><p>✔ Mevcut Framework’un özelliklerini (Kütüphane, metod, işlevlerini) kullanır.</p><blockquote>Mümkün olduğunca çalıştığımız Framework’un sağladığı yapıları kullanmaya çalışmalıyız. Framework şemsiyesinden çıktığımız yerlerde geliştirim ve hata ayıklamalarında kapsam dışında kalırız.</blockquote><blockquote><strong>Hem çalıştığımız platformun sağladığı (.NET, JAVA, vb.) hem de özel olarak projede kullandığımız özel Framework’ler buna dâhildir.</strong> Bu Framework’lerin sağladığı imkanlara hakim olmalıyız. Gerekirse bu konuda mentorumuzdan / koçumuzdan / ilgili dokümantasyondan veya çevrim içi kaynaklardan destek almalıyız.</blockquote><blockquote>Özellikle “string” manipülasyonlar, I/O işlevleri ve matematiksel işlemlerde, sıfırdan kodlamaya başlamadan önce, bu işin acaba ilgili kullandığımız Framework’te yapmanın bir yolu var mıdır diye kısa bir araştırma yapmak faydalı olacaktır.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/613/1*19OtTmNMJ_JYur1qVupQgQ.png" /><figcaption>Date karşılaştırmaları için string çevrimlerine gerek yoktur.</figcaption></figure><p>✔ Kodlar Unit Test ile kapsanır.</p><p>✔ <strong>Teknik borç</strong> yönetilir. <strong>Eritilir</strong>.</p><p>✔ Temiz kod yazımı araçlar ile desteklenir ( Sonarlint, EsLint, Sonarqube, vb.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/483/1*YXrW4jMmgRU3XsUSj3Dq8g.png" /><figcaption>Sonarqube, statik kod analizi yapan harika bir araçtır.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*NAMG6xCBHTBMWcE3qPfSSQ.png" /><figcaption>Çevik yazılım geliştirme prensipleri — 8.Prensip : Yazılım geliştirme sürdürülebilir olmalıdır. Sabit çalışma temposu devam ettirilebilmelidir.</figcaption></figure><p><strong>Temiz kod</strong>, yazılım geliştirme sürecinde <strong>anlaşılabilir</strong>, <strong>sürdürülebilir</strong>, <strong>okunabilir </strong>ve <strong>kolayca bakım yapılabilir </strong>olan kodu ifade eder. Temiz kodun özellikleri şunlardır;</p><p><strong>Okunabilirlik</strong>: Temiz kod, anlaşılır ve açık bir şekilde yazılmıştır. İsimlendirme standartlarına uygun değişken ve fonksiyon isimleri kullanılır. Kodun akışı ve yapısal düzenlemeleri anlaşılır ve mantıklı bir şekilde oluşturulur.</p><p><strong>Basitlik:</strong> Temiz kod, gereksiz karmaşıklıklardan kaçınır. Karmaşık yapılar yerine basit ve anlaşılır tasarımları tercih eder. İşlevler ve sınıflar, tek bir görevi yerine getirmek için küçük ve öz olacak şekilde düzenlenir.</p><p><strong>Uyumluluk</strong>: Temiz kod, kabul edilen standartlara, en iyi uygulamalara ve tasarım prensiplerine uygun olarak yazılır. Kodlama standartları ve kuralları takip edilir, kodun tutarlılığı ve uyumluluğu sağlanır.</p><p><strong>Erişilebilirlik</strong>: Temiz kod, diğer geliştiricilerin kolayca anlayabileceği ve üzerinde çalışabileceği şekilde düzenlenir. İçerdiği işlevler ve modüllerin birbirleriyle uyumlu ve bağımsız çalışabilir olması hedeflenir.</p><p><strong>Test Edilebilirlik</strong>: Yazdığınız kodun unit testini yazmakta zorlanıyorsanız muhtemelen bir şeyde bir şeyi yanlış yaptık demektir. Temiz kod, test etmek için kolayca bölünebilir ve test edilebilir bir yapıda olmalıdır. Kodun bölümleri ayrı ayrı test edilebilir ve hatalar kolayca tespit edilebilir.</p><p><strong>Hata Düzeltme Kolaylığı</strong>: Temiz kod, hataları tespit etmek ve düzeltmek için uygun yapıda olmalıdır. Hata ayıklama ve sorun giderme süreci daha kolay ve verimli olmalıdır.</p><blockquote><strong>Sonuç olarak; Temiz kod yazmak, yazılımın uzun süreli sürdürülebilirliğini, geliştirme sürecini kolaylaştırmayı ve takım çalışmasını iyileştirmeyi sağlar</strong>.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/0*Mp6FlK3CikVsM3Ec.png" /><figcaption>Teknik borç batağına batmamak için bir an evvel düzgün kod yazmaya başlamak gerekir.</figcaption></figure><p><a href="https://blog.crisp.se/2013/07/12/henrikkniberg/the-solution-to-technical-debt">The Solution to Technical Debt - Crisp&#39;s Blog</a></p><h3>❤ KALİTELİ YAZILIM İYİ BİR KULLANICI DENEYİMİ SUNAR.</h3><p>🎯 <strong>Kullanıcı odaklı</strong> bir çözüm sunar. Onların ihtiyaçlarını ve beklentilerini anlar. Onların gereksinimlerine göre tasarlanır.</p><p>🕹️ <strong>Kolay kullanılabilirdir</strong>. <strong>Basit ve sezgisel</strong> bir ara yüz sağlar. Uygulamayı ilk kez kullanan biri eğitime ihtiyaç duymadan onu kolayca kullanmaya başlamalıdır.</p><p>💬 Kullanıcı ile <strong>açık</strong> ve <strong>sade bir dil</strong> ile iletişime geçer. Jargondan kaçınır, yardımcı yönergeler sağlar, hata mesajları bilgilendirici ve yönlendiricidir.</p><p>🎨 Kullanıcılara özelleştirilebilir ve kişiselleştirilmiş deneyimler sunar.</p><p>↩️ <strong>Hata Toleransına</strong> sahiptir. Kullanıcıların hatalar yapabileceğini ön görür. Bunları düzeltmek için uygun geribildirimler ve düzeltme seçenekleri sunar.</p><p>📢 Kaliteli bir yazılım, <strong>kullanıcısına kulak verir</strong>. Hata bildirimlerini ve önerilerini kolayca iletebileceği işlevler sunar. Geri bildirimlere (olumlu veya olumsuz) bir cevap verilir.</p><p>🚀 Değişiklikler ve hata çözümleri <strong>çabuk devreye girer</strong>. Kullanıcı, sorunları ile baş başa bırakılmaz.</p><p>💖 Kullanıcı uygulamayı severek kullanır.</p><h4>Kaçınalım❗</h4><p>❌ Kullanımı zor, işi zorlaştıran ekranlar.</p><p>❌ Özensiz hazırlanmış ve yardımcı olmayan mesajlar.</p><p>❌Uygulamada bir işi halletmek için birden fazla ekranda işlem yapılması.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*VxoxAwGKyNZrT-AuebDHDw.png" /><figcaption>Çözüme sadece yaklaştırabilen bir hata mesajı. Acaba sorun hangi konteynerde?</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*Ws5XS5CS4_fBxA7bjuoNrg.png" /><figcaption>Zaten elimizde var olan bilgiler ilgili mesaja yansıtılmış, kullanıcı sorunu çözmek için tüm bilgilere sahip oldu.</figcaption></figure><h4>Sürdürelim👍</h4><p>✔ Kullanıcı uygulamayı kullanırken önemsendiğini hisseder. Bileşenlerin yerleşimi, akış onun istediği gibi, olması gerektiği zamanda olmasını gerektiği gibidir.</p><p>✔ Kullanıcı istediği çıktıyı üretebilmek için oradan oraya ekranda dolaşmaz veya birden fazla işlem yapmaz.</p><p>✔ Hata çözümleri ve yeni istekler çabuk devreye alınır. Geri bildirimleri karşılık bulur.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c3c4cf01b451" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/kaliteli-yaz%C4%B1l%C4%B1m%C4%B1n-nitelikleri-temiz-kod-c3c4cf01b451">Kaliteli Yazılımın Nitelikleri &amp; Temiz Kod+</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sahadan Temiz Kod - İsimlendirmeler]]></title>
            <link>https://medium.com/bimar-teknoloji/sahadan-temiz-kod-i%CC%87simlendirmeler-ab48a03dbb3c?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/ab48a03dbb3c</guid>
            <category><![CDATA[clean-code]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[temiz-kod]]></category>
            <category><![CDATA[yazilim-gelistirme]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:33:30 GMT</pubDate>
            <atom:updated>2020-10-19T16:03:51.524Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/543/1*l3LmX3ZjjZ92VDRE6aVMqw.png" /></figure><p>Yazılım geliştirmede isimlendirme işini ne küçümsemek ne de abartmak doğrudur. <em>Önemli olan nokta isimlendirmedeki şansımızı, bizden sonraki yazılımcıya mümkün olan en doğru mesajı verecek şekilde ustaca kullanmaktır.</em></p><p>İsimlendirmelerde <strong>dokunduğu yeri en iyi anlatan, en sade </strong>tercihi yapmanız gerekir.</p><p><a href="https://serkanapul.medium.com/kaliteli-yaz%C4%B1l%C4%B1m%C4%B1n-nitelikleri-temiz-kod-c3c4cf01b451">Kaliteli bir uygulamanın</a> bakımı kolaydır. Uygun isimlendirme tercihleri kodun bakımına dolayısıyla kalitesine olumlu katkı sunar. İsimlendirme konusunun önemi buradan gelmektedir. Şimdi, daha önce okuduğum kodlarda karşılaştığım bazı <em>geliştirilebilir isimlendirme örneklerini</em> aktarmaya çalışacağım.</p><h3>Olumsuz İfade Kullanmak ❌</h3><p>İnsan beyni olumlu bir ifadeyi daha rahat çözer. O nedenle <strong>ToplamAgirligaDaraDahilEdilmeyecekMi</strong> şeklinde bir ifadeyi anlamakta biraz zorlanabiliriz. Bunun yerine üzerinde biraz düşünüp <strong>DaraHaricMi </strong>diye bir tercihte bulunabiliriz.</p><p>Yapıl<strong>mamalı</strong> yerine EngellensinMi, GözArdiEdilsinMi gibi ifadeleri kullanabiliriz.</p><h3>Özel İsim Kullanmak ❌</h3><p>Bir rapor veya kod sınıfını, veya hesap yapan bir metodu isimlendirirken “<strong>İspanya</strong>MuhasebeRaporu”, “<strong>İzmir</strong>Konsimentosu” gibi ifadelerden kaçınalım. “<strong>AltToplamDetayli</strong>MuhasebeRaporu” “<strong>Yaldizli</strong>Konsimento” gibi <strong><em>sınıfın/raporun içeriğinden esinlenmiş </em></strong>isimler tercih edelim. Böylece bu özelliğe sahip ilerideki kullanımlar ( örneğe göre başka bir ülke) için aynı sınıfı kullanmak aklımıza gelecektir. Tersi durumda genelde kopyalanıp ismi değiştirilir. Kopya kod olacağı için bunu istemeyiz.</p><p><em>(Bu kuralın tek istisnası şudur: Örneğin Aliağa limanı logolu, sadece Aliağa limanındaki sistemde çalışan, </em><strong><em>başka bir limanda kullanılması hemen hemen imkansız </em></strong><em>özel rapor ve sayfalar istisnadır. Bunları en iyi ifade eden isim gerçekten AliagaRaporu olacaktır.)</em></p><h3>Abartılmış Metot Adları❌</h3><p>public void FaturaDurumu<strong>Stopajsa</strong>Degistir(…) Metot isminde, metodu çağıran sınıfı ilgilendirmeyen, metodun o işi hangi iş kuralına göre yaptığına dair detaya yer verilmez. Bu detay değişebilir,metot ismi bu değişiklikten etkilenmemelidir.</p><p>Doğrusu; public void FaturaDurumuDegistir(…)</p><h3>Parametrelerden Edineceğim Bilgiyi Metot İsminde Tekrar Etmek ❌</h3><p>public string <strong>TipTurKullanarak</strong>SistemDonusumGetir(long <strong>tipId</strong>, long <strong>turId</strong>)</p><p>Metot adında parametre isimlerini barındırmanın gerek yoktur. Aksi taktirde parametre ara yüzü değişirse metot ismi uygunsuz hale gelir.</p><p>Unutmayalım. Metodun ne iş yaptığını ne döndüğünü neler kabul ettiğini sadece adından anlaşılmaz. <strong>Parametre setim</strong> ve <strong>dönüş tipim</strong> de, metot ismi ile birlikte bir şeyler söylüyorlar. Bunların aynı şeyi tekrar etmelerine gerek yoktur.</p><p>Doğrusu; public string SistemDonusumGetir(long tipId, long turId)</p><h3>Büyük Metodun İsmine Yansıması ❌</h3><p>private void FaturaOnayla<strong>Ve</strong>Gonder(..) -&gt; Kendinizi bu şekilde isimlendirme yaparken bağlaç kullanırken buluyorsanız belli ki bir şeyler ters gitmiştir. Bu örnek için metodun birden fazla iş yapıyor olmasından şüphelenebilirsiniz ve bunları ayırmayı düşünebilirsiniz.</p><p>Doğrusu ; private void FaturaOnayla(..)</p><h3>Metot İsminin Dönüş Tipine Uydurulması ❌</h3><p>private DataTable PersonelAdSoyadTelefonBilgisiDondur(..) -&gt; Bu örnekte <strong>metodun dönüş tipini</strong> tekrar değerlendirmek gerekir. Bu “ad soyad telefon” bilgilerini bir arada tutan ne ise, başka bir deyişle bunların hepsini kapsayan ifade ne ise onu kullanmak gerekir. Sonrasında bu ifadeye uygun bir sınıf yaratmak ve dönüş tipi olarak bunu kullanmak en uygun çözüm olacaktır.</p><p>Doğrusu ; private <strong>IletisimBilgi</strong> PersonelBilgiDondur(…) (IletisimBilgi,ad, soyad ve telefon bilgisini içeren yeni bir sınıftır)</p><h3>⭐İsimlendirmedeki Güzel Pratikler ⭐</h3><blockquote><em>Tanımladığımız sabitin birimi hakkında net olmak için, değişken ismine bu birimi eklemek güzel bir pratiktir.</em></blockquote><blockquote>long timeOut<strong>InSeconds</strong> = 60</blockquote><blockquote>long maxFileUploadSize<strong>InMb</strong>=5</blockquote><p>Esen Kalın</p><p>Serkan</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab48a03dbb3c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/sahadan-temiz-kod-i%CC%87simlendirmeler-ab48a03dbb3c">Sahadan Temiz Kod - İsimlendirmeler</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bir çukurun içindeysek, işe kazmayı bırakmakla başlamalıyız.]]></title>
            <link>https://medium.com/bimar-teknoloji/bir-%C3%A7ukurun-i%C3%A7indeysek-i%C5%9Fe-kazmay%C4%B1-b%C4%B1rakmakla-ba%C5%9Flamal%C4%B1y%C4%B1z-a3bc3d679d20?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/a3bc3d679d20</guid>
            <category><![CDATA[temiz-kod]]></category>
            <category><![CDATA[yazılım-kalitesi]]></category>
            <category><![CDATA[yazilim-gelistirme]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:33:05 GMT</pubDate>
            <atom:updated>2020-11-26T12:20:17.301Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/461/1*Ga3LCulQlr9cbUUk_kuVrQ.png" /></figure><p>Bu sözü, yazılım işi için “<strong>Teknik borcu kapatamıyorsan</strong>, en azından <strong>daha fazla borçlanma</strong>” diye çevirebiliriz.</p><p>Zira, o an için aslında ‘<strong>yanlış olduğunu bildiğimiz</strong>’ fakat ‘<strong>daha az zaman almasının</strong>’ cazibesine kapıldığımız bu seçimler, var olan <strong>sorunu derinleştiriyor </strong>ve eninde sonunda zamanı gelince birinin <strong>yapmaya mecbur kaldığı düzeltmeyi</strong>/iyileştirmeyi (aslında bir ‘Refactor’ü ) <strong>zorlaştırıyor</strong>.</p><p>Benim tecrübe ettiğim bazı <em>‘kazmayı bırakma anları’</em> şunlar;</p><ul><li>Bu class’da zaten hiç yazılmamış diyerek, birim test’i yazmayı es geçmek yerine, artık her değişiklikte ve yeni geliştirimde birim testlerini yazmak.</li><li>İhtiyacımız olduğunda, düşük performanslı veya güvensiz, “önceden yazılmış hazır” bir metodu o şekli ile kullanmaya devam etmek yerine, yenisini yazıp, üstüne önceki çağırımları da iyileştirmek.</li><li>2 yaşına girmiş 20+ açık Sonarqube Issue’ların (Statik kod taraması sonucunda çıkan bulguların) hepsinin birlikte planlanması beklemeyi bırakıp, artık yeni Issue’ları aynı Sprint’te kapatmaya başlamak.</li></ul><p>Sizin de eğer varsa <em>kazmayı bıraktığınız anlarınızı</em> burada paylaşırsanız, minnettar olurum.</p><p>Esen Kalın.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a3bc3d679d20" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/bir-%C3%A7ukurun-i%C3%A7indeysek-i%C5%9Fe-kazmay%C4%B1-b%C4%B1rakmakla-ba%C5%9Flamal%C4%B1y%C4%B1z-a3bc3d679d20">Bir çukurun içindeysek, işe kazmayı bırakmakla başlamalıyız.</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bir yerden başlamak : Devops]]></title>
            <link>https://medium.com/bimar-teknoloji/bir-yerden-ba%C5%9Flamak-devops-12c3d90baf24?source=rss----92f06038ce70---4</link>
            <guid isPermaLink="false">https://medium.com/p/12c3d90baf24</guid>
            <category><![CDATA[yazılım-geliştirme]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[çevik-yazılım-geliştirme]]></category>
            <dc:creator><![CDATA[Serkan Apul]]></dc:creator>
            <pubDate>Mon, 09 Dec 2024 08:32:57 GMT</pubDate>
            <atom:updated>2023-06-04T14:22:24.633Z</atom:updated>
            <content:encoded><![CDATA[<h3>Bir yerden başlamak : Devops</h3><p><strong>Devops</strong>, yazılım değişikliklerini <strong>hızlı </strong>ve <strong>güvenli </strong>bir şekilde yapma amacı taşıyan <strong>yaklaşım </strong>ve <strong>uygulamalardır</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/672/1*EzGI7MprdyRnewe5r5TTxQ.png" /><figcaption>Hızlı ve Güvenli — The Gurkha</figcaption></figure><p>“Devops yapmak”, “Agile olmak”, bunlar el ele tutuşup hep birlikte karşı tarafa atlayabileceğimiz bir şeyler gibi anlatılabilir, bu şekilde anlaşılabilir. Halbuki bunlar birer süreçtir ve “top yekûn” geçişten önce yapabileceğimiz seçimler, hayata geçirebileceğimiz uygulamalar vardır.</p><p><strong>Devops</strong> hem taleplerinin hızla gerçekleştirilmesini bekleyen <strong>“tez canlı” Developer’ların</strong>, hem de her günü sistemlerin güvenli ve kesintisiz çalışması stresi ile geçen <strong>“ihtiyatlı” sistemcilerin </strong>endişelerini ortadan kaldıracak, onların uyum içinde beraber çalışmasını sağlayacak uygulamalardır diyebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/369/1*bWeUFYk2Rp3Y9Gyy-PmU1g.png" /><figcaption>Devops bu duvarın yıkılmasına hizmet eder.</figcaption></figure><blockquote>Değişiklikler <strong>çabuk</strong> ve <strong>güvenli</strong> şekilde gerçekleştirilmelidir.</blockquote><blockquote>Devops <strong>kaynakların kapasitesini artırmak</strong> için kullanılır.</blockquote><blockquote><strong>Silolar, üretim ve kalitenin düşmanıdır.</strong></blockquote><p><strong>Devops Unsurları (CALMS) : </strong>Bu yazının, bir sunumun kopyası olmasını istemiyorum. <a href="https://www.atlassian.com/devops/frameworks/calms-framework">Linkini </a>bırakıyorum. Burada not düşmek istediğim şudur. Devops unsurlarını gerçekleştirirken <strong>araçlara aşırı anlam yüklemeyin</strong>. Bu unsurların hepsi eşit derecede önemlidir.</p><p>Aşağıdaki unsurlarda yapacağız her iyileştirme ve yeni adım sizi tam gerçekleşmiş bir devops ortamına bir adım daha yaklaştıracaktır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tQr-tx0dCGub57dW-E_o4Q.png" /><figcaption>Keep C.A.L.M.S. and Devops</figcaption></figure><h3><strong>Tecrübe Edilmiş Gerçekler</strong></h3><p><strong>En</strong> <strong>önemli kaynak insan kaynağıdır</strong>. Devops dahil tüm değişim hareketlerin başarısını etkileyen, üzerinde en çok düşünülmesi gereken unsurdur. (Google araştırması : bir takımın etkinliğinde en önemli faktör kişinin güvenlik hissi olduğunu ortaya koymuştur. Bakınız <a href="https://rework.withgoogle.com/print/guides/5721312655835136/">Project Aristotle</a>)</p><p>Olay sadece araç değişimi değildir. Hiç bir zaman bu olmamıştır. <strong>İnsanların toplu uyumu ve mutluluğu önemlidir</strong>.</p><p><strong>Yönetim kademesinin</strong> Devops’a ( veya herhangi bir değişime) <strong>inanması</strong> başarıyı şansını artırıyor ( bunun tam tersi, yani inanmıyor olması çok büyük ihtimal ile başarısızlık “FAIL” sebebi oluyor.)</p><p><strong>Suçlama yapmayan</strong>, “<strong>post-mortem</strong>” <strong>kültürünü yüceltmek gerekiyor</strong>. Suçlama olursa insanlar risk almaktan çekinmeye başlar. Fikir beyan edilmeyen, risk alınıp bir şey denenmeyen bir ortamda bir şeylerin iyileşme ( değişme ) şansı olmaz.</p><p><strong>Efor sarf edilen her iş, sistemde bir iş maddesi olarak ifade edilmelidir. </strong>Örneğin yeni bir modül için kodu yazıyorsunuz, bu esnada bu iş için yeni bir sunucunun ayağa kaldırılması gerektiği anlaşıldı. Bu iş için tıpkı sizin “kod yazma” iş maddeniz gibi, “sunucu kurma” iş maddesi de, aynı iş maddesi sisteminde yer almalıdır. Ancak böyle yaparak tüm beklemeleri, bunun yanında müşterinin modülü istemesi ile bu modülün devreye girmesi için geçen süreyi gibi değerleri sistemden çekebilirsiniz.</p><p><strong>Araç sayısını ne kadar azaltırsak o kadar iyidir</strong>. Az araç entegrasyonu azaltır, iletişimi artırır. Seçilen araç, şirketin stratejisine uygun olmalıdır.</p><p><strong>Teknik borç görünür olmalıdır</strong>. Mümkünse ekiplerin takip ettikleri ana ekranlarında ( dashboard üstünde)görünmelidir.</p><p><strong>Belirlediğiniz KPI’lar</strong> <strong>müşteriye değer katan, toplam etkiyi </strong>( TOTAL IMPACT ) <strong>artıran nitelikte olmalıdır</strong>.</p><p>Devops’a değişimine uyum sağlayan ve <strong>çevresini yeşerten kişiler mükafatlandırılmalıdır</strong>. <strong>Ödül kriterleri net ise, ödül her zaman olumlu algılanır.</strong></p><p><strong>IT dönüşümü zorlayıcıdır</strong>. Yolun başında — ortasında — sonunda bu akıldan çıkartılmamalıdır.</p><h3>Uygulama Dönük Öneriler</h3><p>💡 XP Çalışma -Cross Functional Ekipler-: Biri kod yazıyor biri test yazıyor sonra rolleri değişiyorlar. Bunu aynı ekip içinde yapmak çapraz olarak yetkinliklerin artmasını sağlıyor.</p><p>💡 Uygulamanıza <strong>geri bildirim alan bir “widget” yapıp</strong>, bunu farklı bir tiple bir “ticket” olarak açabilirsiniz (Örneğin Azure Devops içinde PBI olarak olarak düşünülebilir.) Müşteri memnuniyetini artıracak bir faaliyettir.</p><p>💡 <strong>BUG açan bir “widget” yapabilirsiniz</strong>. Ekran görüntüsü ve detaylı bilgi alabilir. Gerçekten hata ise açabilmelidir. Basit bir form yaparsak istismar edilebilir.</p><p>💡 <strong>Bug Cap</strong> : Hata sayısı belli bir adedi aştığında ekibin kalemi kağıdı bırakıp hataları eritmesidir. Ekip bölünmemek için hata adetlerini aşağıda tutmak için yenilikçi ve kalıcı çözümler bulur. <a href="https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/agile-principles-in-practice">Agile principles in practice — Azure DevOps | Microsoft Docs</a></p><p>💡 <strong>Bireysel KPI önerisi</strong>: <strong>Başkalarının (internal/external/customer centric) başarısı için ne yaptın?</strong> Onlara hangi yetkinlikleri kazandırdın? (Contribute to Others success) Birlikte çalışmayı motive eden harika bir performans ölçme kriteri olabilir.</p><p>💡 <strong>Dev ve Ops ekipleri </strong>(katkı verdikleri hizmetler üzerinden) <strong>ortak KPI verebilir. (MTTR)</strong> Örneğin kurumsal bir ERP uygulamasının yeni bir ülkede zamanında devreye alımı bu iki ekip için ortak bir hedef olmalıdır.</p><p>💡 <strong>Müşteriyi işin içine katınız.</strong> Örneğin Microsoft’ta her ürün için, içinde müşterilerin olduğu bir TEAMS Kanalı açması şarttır. (Uygulamalarımız için düşünebiliriz. X Uygulaması için içinde bir şekilde müşterinin / anahtar kullanıcıların bulunduğu bir kanal olabilir. )</p><p>💡 <strong>Her türlü kaynak</strong> (script, kod, doküman) bir <strong>Repository’de tutulmalıdır</strong>. Bu, öneriden daha çok bir olmazsa olmazdır.</p><h3><strong>Yönetimin arkasında durması gerekecek işler</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/618/1*Sfl_R_8OHIvCpdVtaVitcw.png" /><figcaption>Photo by <a href="https://unsplash.com/@lebrvn?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Romain V</a> on <a href="https://unsplash.com/s/photos/executive-meeting?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>💬<strong>Kurumun stratejisi hızlanmak</strong> yönünde olmalıdır.</p><p>💬 Kurum içinde <strong>KPI verme alışkanlığının yerleştirilmesi</strong> gerekir.</p><p>💬 Devops dönüşümüne hizmet edecek faaliyetler içini, İş listesi uygulamasında ( Örneğin Azure Devops — Backlogs kullanılarak) yeni bir iş maddesi açıp ( IT modernizasyon gibi) kurumun vizyonuna uygun misyonlar ve yapılacak görevler, bitiş tarihi ile hedef olarak verilmesi sağlanmalıdır.</p><p>💬 Sisteminizde “<strong>Monitoring Reader</strong>” rolünün daha fazla kişide olmasının bir sakıncası yoktur. Sistem ve Developer ekipleri bu yetkiyi paylaşabilir.</p><p>💬 <strong>Kimseyi üzmeyen basit kararlar hemen alınabilir</strong>. (Microsoft Teams’de veya SLACK içinde artık kurum neyi kullanıyorsa birlikte çalışan dev ve ops ekiplerinin ortak amaçlarına uygun yeni kanal açması gibi)</p><p>💬 <strong>Değişim belli bir grupta başlatıldıysa</strong>, o grupta devreye aldıktan kısa bir süre sonra (yaygınlaştırma yapmadan önce) <strong>mutlaka geri bildirim alınmalıdır.</strong></p><p>💬 Devops dahil her değişim planında <strong>Sponsor aktivitelerinin</strong> ( CEO ‘nun neyi zaman duyuracağı, başlatacağının) belirlenmesi çok önemlidir.</p><p>💬 <strong>Her üründe mutlaka </strong>( ürünün karlılığından sorumlu, ürünün amacına uygun geliştirilmesinde son kararı verecek) bir <strong>ürün sahibi (Product Owner -PO) olmalıdır</strong>.</p><p>💬<strong>Şeffaflık</strong>, <strong>takımlarda otonomi</strong> mümkün olduğunca sağlanmalıdır.</p><p>Umarım buraya kadar gelmenizi sağlayabildim. “Devops dönüşümü” notlarımı mümkün olduğunca sade, içerisinden alıp hayata geçirilebilecek şekilde paylaşmaya çalıştım. Biraz uzun oldu farkındayım, bununla birlikte daha fazla fayda sağlayabilme şansımı azaltmak istemediğimden değerli gördüğüm hiç bir noktayı atlamak istemedim.</p><p>Sağlıkla ve pozitif kalın 💗🚀</p><p>Sevgiler</p><p>Serkan</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=12c3d90baf24" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bimar-teknoloji/bir-yerden-ba%C5%9Flamak-devops-12c3d90baf24">Bir yerden başlamak : Devops</a> was originally published in <a href="https://medium.com/bimar-teknoloji">Bimar Teknoloji Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>