Mehmet Sağır

Blogs

VS Code Nasıl Daha Verimli Kullanılabilir?

Visual Studio Code şahsen benim gördüğüm kullanımı en basit ve en özelleştirilebilir editörlerden biri. Bazı eklenti ve ayarlar ile birlikte neredeyse tüm ayarlarını kendimize göre özelleştirebilmek mümkün. Bu makale ile birlikte çoğu geliştiricinin kullanmadığını fark ettiğim bazı özelleştirmelerden bahsedeceğim. Snippets Örnek olarak bir HTML sayfasında html:5 yazdığımızda bize HTML şablonu oluşturur. Bu gibi VS Code içerisinde hali hazırda gelen Snippet’lar mevcut. Buna ek olarak ES7+ snippets gibi eklentiler ile birlikte ekstra Snippet’lar da kullanabiliyoruz. Peki biz kendimiz bir Snippet oluşturmak istersek bunu nasıl yapabiliriz? Bunun için VS Code `Command Palette` kısmını açarak (mac: shift+cmd+p | windows: shift+alt+p) `snippets` yazıyoruz ve `Configure User Snippets` kısmına giriyoruz. Buraya girdikten sonra bizi aşağıda gördüğünüz gibi bir alan karşılıyor. Burada hali hazırda dil ve Frameworkler için JSON dosyaları mevcut. İstersek buradan istediğimiz bir dili seçip sadece o dile özgü Snippet’lar oluşturabilir veya `New Global Snippets file` seçeneğini seçip yeni oluşturulacak dosyaya istediğimiz bir ismi girerek global bir Snippet dosyası oluşturabiliriz. Bu oluşan sayfada bizi örnek kullanım ve bazı açıklamalar karşılıyor. Örnek olarak bir React Component içerisine styled-components dahil edip ismini bizden alacak ve sonrasında kullanıma hazır hale gelecek şekilde oluşturmak istediğimizi varsayalım. "Print to React Component with styled-components": { "scope": "javascriptreact, typescriptreact", "prefix": "rsc", "body": [ "import React from 'react';", "import styled from 'styled-components';", "", "function $0() {", " return ", " $0", " ", "}", "", "const Styled$0 = styled.div``;", "", "export default $0" ], "description": "React component with styled-components" } Snippet, Key ve Value şeklinde yazılıyor. Oluşturduğumuz bu dosya içerisinde Key tekil olmak zorunda olduğu için Snippet’ın ne yaptığını basit bir şekilde anlatıyoruz. Sonrasında Value tarafına geldiğimizde burada bizden Scope, Prefix, Body ve Description alanlarını istiyor. Scope: Bu Snippet hangi dil veya Framework’e ait dosyalarda çalışacaksa onu yazıyoruz. Prefix: Snippet’ı ne yazdığımızda kullanmak istiyorsak onu belirtiyoruz. Biz burada rsc (React Styled Component) olarak belirledik. Body: Buraya yazılmasını istediğimiz kod parçasını ekliyoruz. Description: Snippet bizim için ne yapıyor ise onu açıklıyoruz. Tüm bu alanları doldurduktan ve kaydettikten sonra herhangi bir JavaScript dosyasına gelip `rsc` yazdığımızda resimde de gördüğünüz gibi Key, Body ve Description alanları önizleme içerisinde gösteriliyor. Son olarak bu oluşturduğumuz Snippet’ı kullandığımızda bizden sadece Component adını isteyen, içerisine Styled Components dahil edilmiş ve kullanıma hazır hale gelmiş bir React Component’i oluşturmuş oluyoruz. Bunun gibi gün içerisinde sürekli olarak yazdığınız kodları bir Snippet haline getirerek zamandan ciddi anlamda tasarruf sağlayabilirsiniz. Tüm bu işlemleri Snippet Generator sitesi üzerinden yapıp çıktıyı oluşturduğumuz dosyaya ekleyebilirsiniz. Keyboard Shortcuts VS Code tarafında tüm klavye kısayollarını görebildiğimiz ve kendimize göre özelleştirebildiğimiz bir alan mevcut. Buraya girebilmek için Ayarlar altından `Keyboard Shortcuts`(Mac: CMD+K CMD+S | Windows: ALT+K ALT+S) alanına geliyoruz. Burada hangi işlemin kısayoluna bakmak veya değiştirmek istiyorsak o işlemi ismi ile veya sağ tarafta yer alan klavye ikonuna tıklayarak klavye kısayolları ile arayabiliyoruz. Kısayolunu değiştirmek veya ek bir klavye kısayolu eklemek istediğimiz işlemi bulduktan sonra `Keybinding` kısmına sağ tıklayarak yapmak istediğimiz işlemi seçip gerçekleştirebiliyoruz. Benim sıklıkla kullandığım örnek klavye kısayolları: CMD+J: Toggle Terminal Control+S(When: terminalFocus): Split Terminal Control+A: Toggle Activity Bar Visibility Control+S: Show Source Control Control+F: Show Explorer Control+X: Find in Files Control+C: Toggle Sidebar Extensions Auto Close Tag : Bu eklenti yazdığınız HTML etiketlerinin kapanışını otomatik olarak tamamlar. Auto Rename Tag : HTML etiketini değiştirmek istediğinizde kapanış etiketini açılış etiketine göre anlık olarak günceller. Color Highlight : Yazmış olduğunuz renk, arkaplan rengi olarak ayarlanır. Error Lens : Kod içerisinde oluşan hata ve uyarıların üzerine gelmeden okunmasını sağlar. Path Intellisense : Girmiş olduğunuz yola göre dosya adlarını otomatik olarak tamamlar. Todo Tree : Sayfalar içerisinde yazılmış olan yorum satırlarını istenilen formatta yazdığımızda, hepsinin toplu bir yerden görüntülenmesini ve formata göre renklendirilmesini sağlar. Version Lens : Proje içerisinde kullandığımız paketlerin güncel versiyonlarını gösterir ve güncellememizi sağlar. Diğer eklentiler: Prettier — Code formatter , ESLint , vscode-styled-components , Live Share , Live Server , Tailwind CSS IntelliSense Son olarak kendinize uygun temayı bulabilmek için VSCode Themes sitesine bir göz atabilirsiniz. Okuduğunuz için teşekkürler 🥳 VS Code Nasıl Daha Verimli Kullanılabilir? was originally published in FowApps on Medium, where people are continuing the conversation by highlighting and responding to this story.

JavaScript Engine, Memory Leaks

Bu makalede Memory Leaks (Bellek Sızıntısı) nedir? Ne gibi durumlarda karşımıza çıkar ve bellek sızıntılarından nasıl kaçınırız gibi soruları cevaplayacağız. Bildiğiniz gibi JavaScript motoru, değişken ve nesneler tanımlandığında geliştiricinin müdahalesi olmadan bellek üzerinde bir yer tahsil eder ve artık bellek tarafında tutulmasına gerek kalmayan durumlarda değişken ve nesneleri kaldırarak belleği boşaltır. Bellek yönetiminin temel aşamalarını hatırlayacak olursak; Bellek alanı tahsil et Kullan (Okuma ve yazma) Temizle (İhtiyaç duyulmayan nesne ve değişkenlerin bellekten kaldırılması) Son aşama olan ihtiyaç duyulmayan nesne ve değişkenlerin bellekten kaldırılma işini bizim için çöp toplayıcı yapar. Aslında Memory Management (bellek yönetimi) konusunda JavaScript, geliştiricinin bir müdahalesini beklemez. Tüm işlemleri arka planda otomatik olarak gerçekleştirir. Fakat bu, biz geliştiricilerin bu konuyu önemsemeden devam edebileceği anlamına gelmez. Yaptığımız mantıksal bir hata bellek tarafında tanımlanan değişken veya nesnenin kaldırılamamasına yol açabilir. Bu da uygulamanın yavaş çalışmasına, yüksek gecikme sürelerine ve hatta çökmelere sebep olur. Özetle bellek sızıntısı, bellek tarafında kullanılmayı bekleyen unutulmuş verilerdir. Bellek sızıntısına yol açacak bir kod parçasını incelemek isterseniz boş bir dizi tanımlayıp sonsuz bir döngü içerisinde o diziye değer ekleyebilirsiniz. const arr = []; while(true) { arr.push(Math.random()) } Bu kod parçası Chrome üzerinde bulunduğunuz sekmeyi çökertecektir. Yaygın Bellek Sızıntıları 1- Global Değişkenler JavaScript’te tanımlanmamış değişkene yapılan çağrı global nesnenin içinde yeni bir değişken oluşturur. Global değişkenler her zaman kökten elde edilebilir ve hiçbir zaman çöp toplayıcı tarafından toplanmaz. Tarayıcı üzerinde bu Window’u temsil eder. name = "Mehmet" Bu şekilde yazılmış bir kod, window.name = "Mehmet" Aslında bu şekilde algılanır. Bu tarz hataların önüne geçebilmek için JavaScript dosyalarınızın başına ' use strict ' yazarak daha katı JavaScript ayrıştırma moduna sahip olabilirsiniz. 2- Zamanlayıcılar setTimeout veya setInterval ile bir nesneye atıfta bulunmak, nesnenin çöp toplayıcı tarafından temizlenememesinin en yaygın yoludur. Aşağıdaki örnekte nesne yalnızca zamanlayıcı temizlendikten sonra çöp toplayıcı tarafından temizlenir. Referansımız olmadığı için Interval asla silinmez ve data.hugeStringhiç kullanılmasa da uygulama durana kadar hafızada tutulur. function setCallback() { const data = { counter: 0, hugeString: new Array(100000).join('x') }; return function cb() { data.counter++; console.log(data.counter); } } setInterval(setCallback(), 1000); Bunu önlemek için zamanlayıcıyı bir şarta bağlayarak veya bir tetikleyici ile ‘clearInterval’ kullanarak temizleyebiliriz. const btn = document.getElementById("btn") function setCallback() { const data = { counter: 0, hugeString: new Array(100000).join('x') }; return function cb() { data.counter++; console.log(data.counter); } } const interval = setInterval(setCallback(), 1000); /** if (true) { // your condition clearInterval(interval); } */ // or btn.addEventListener("click", () => { clearInterval(interval) }, { once: true }) 3- Olay dinleyicileri Olay dinleyici, kapsamında bulunan tüm değişkenlerin çöp toplayıcı tarafından toplanmasını önleyecektir. DOM öğesi, Nesne Grafiği Belleğinde de bulunur. Bu nedenle, ilkini silerseniz ikincisini de silmeniz gerekir. const btn = document.getElementById("btn"); const text = document.getElementById("text"); btn.addEventListener("click", () => { text.remove(); }); Örnekte gördüğünüz gibi buton elemanına tıklanınca Text elemanı DOM’dan kaldırılır. Ancak dinleyici için ayrılan bellek hala kullanılır. const btn = document.getElementById("btn"); const text = document.getElementById("text"); btn.addEventListener("click", () => { text.remove(); }, { once: true }); Bunu engellemek için işlem bittiğinde removeEventListener ile dinleyiciyi temizleyebilir veya örnekteki gibi üçüncü bir parametre olarak once: true diyerek dinleyicinin olayı bir defa işledikten sonra sonlanmasını sağlayabiliriz. JavaScript bellek sızıntılarını belirleyip düzeltmek süreç ilerledikçe daha zorlu bir göreve dönüşebilir. Bu nedenle en mantıklı çözüm, bellek yönetimi sürecinin ayrılmaz bir parçası tipik bellek sızıntısı kaynaklarını anlamak ve bunların olmasını en baştan önlemektir. Sonuç olarak konu bellek ve performans ve söz konusu olan kullanıcı deneyimidir. Okuduğunuz için teşekkürler 🥳 Kaynaklar: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/ JavaScript Engine, Memory Leaks was originally published in FowApps on Medium, where people are continuing the conversation by highlighting and responding to this story.

Stack Overflow — Garbage Collection

Stack Overflow — Garbage Collection Stack Overflow konusuna bakmadan önce Call Stack (Çağrı yığını) kavramını biliyor olmamız gerekiyor. Kısaca özetlemek gerekirse; Call Stack: Yürütmenin devam edeceği adresi ve her çağrıdan var ise yerel değişkenleri ve parametreleri içeren bir LIFO veri yapısıdır. Stack içerisinde tutulan ilkel veri tiplerinin boyutları sabittir ve kod yürütülmeden önce bellekte ona göre yer ayrılmıştır. İlkel değerlerin ne kadar büyük olabileceğinin bir sınırı vardır. Bu sınır aynı şekilde yığının kendisi için de geçerlidir. Daha detaylı bilgi için ‘ JavaScript Engine, Stack — Heap’ . Stack Overflow (Yığın Taşması) Az önce de bahsettiğim gibi çağrı yığınına atanmış maksimum bir boyut vardır. Yığın taşması, yığına sürekli olarak işlemlerin eklenmesi ancak yığından kaldırılamamasından dolayı oluşur. Basit bir Recursion (öz yineleme) örneği ile bu durumu inceleyelim. function recursion() { recursion() } recursion() Bu fonksiyon kullanımı ‘Recursive Function’ olarak isimlendirilir. Tanımı ve örnek kullanımlarına buradan erişebilirsiniz. Bu kodu kendi tarayıcınız üzerinden test ederseniz size ‘Maximum Call Stack size Exceeded’ hatası döndürecektir. Call Stack üzerinde örnek görünümü ise bu şekildedir. Özetlemek istersek Stack Overflow, sabit boyuta sahip olan Stack üzerinde işlemlerin sonlandırılamamasından kaynaklı olarak taşmadan oluşan hatadır. Garbage Collection Low Level dillerde bellek yönetimi geliştiricinin açık müdahalesine ihtiyaç duymaktadır. Örnek olarak C gibi Low Level bir programlama dili, ihtiyaç duyulmayan nesne ve değişkenleri bellek tarafından temizlemek için geliştiricinin malloc() ve free() gibi yöntemleri kullanmasını bekler. Ancak JavaScript gibi high level diller için durum bu şekilde değildir. High Level dillerde bellek yönetimi otomatikleştirilmiştir ve geliştiricinin müdahale etmesi beklenmez. Süreci daha iyi anlayabilmek için bellek yönetiminin genel yaşam döngüsüne bir göz atalım. İlk olarak tanımlanan nesne, değişken ve fonksiyonlar için bellek tarafında bir alan tahsil edilir. Sonrasında okuma/yazma işlemleri için kullanılır. Son olarak ihtiyaç duyulmadığı durumlarda ise silinir ve bellek alanı serbest bırakılır. Son adımı gerçekleştiren mekanizmaya Garbage Collector (Çöp Toplayıcı), bu duruma ise Garbage Collection (Çöp Toplama) denir. Çöp toplama işleminin gerçekleştirilmesi için bahsedilen değerin kullanılmaması ve herhangi bir referansının bulunmaması gerekmektedir. Bir örnek ile inceleyelim. İlk olarak ‘person’ adında global bir değişkenimiz olsun ve bu değişkene bir değer atayalım. Sonrasında bu değeri null olarak güncelleyelim. let person = { name: "Mehmet" } person = null Bu tarz bir durumda ilk değerimizin herhangi bir referansı olmadığı ve herhangi bir yerde kullanılmadığı, yani ulaşılamaz olduğu için Çöp Toplayıcı tarafından temizlenecektir. Şimdi ‘myInfo’ adında farklı bir global değişken tanımlayarak person değişkenin referansını myInfo değişkenine kopyalayalım. let person = { name: "Mehmet" } const myInfo = person person = null Bu durumda person değişkeninin değerini değiştirmiş olmamıza rağmen myInfo, nesnemizin referansını tuttuğu için Çöp Toplayıcı tarafından temizlenmeyecektir. Özet olarak Çöp Toplayıcı sürekli olarak belleği izleyerek kullanılmayan ve bir referansı olmayan değerlerin bellek tarafından temizlenmesidir. Okuduğunuz için teşekkürler 🥳 Stack Overflow — Garbage Collection was originally published in FowApps on Medium, where people are continuing the conversation by highlighting and responding to this story.

JavaScript Engine, Stack — Heap

JavaScript Engine, Stack — Heap Stack ve Heap konularına değinmeden önce kısaca JavaScript Engine nedir, bizim için ne iş yapar ona bir bakalım. JavaScript Engine En temelde JavaScript Engine yazdığımız kodu çalıştırabilmek için bilgisayarın anlayacağı dile dönüştüren bir yazılım bileşenidir. Bunları örneklendirmek istersek; JavaScript’in de yaratıcısı olan Brendan Eich tarafından 1995 yılında geliştirilen SpiderMonkey , aynı zamanda geliştirilmiş olan ilk JavaScript motorudur. Günümüzde geliştirilmesi Mozilla vakfı tarafından devam etmekte ve Firefox web tarayıcısında kullanılmaktadır. V8, Google Chrome için Chromium projesi kapsamında geliştirilen günümüzün en popüler JavaScript motorudur. Hem istemci (Google Chrome) hem de sunucu (Node.js) tarafı JavaScript uygulamaları için kullanılmaktadır. Aynı zamanda açık kaynak olarak geliştirilmesi devam etmektedir. V8 Motoruna Genel Bakış V8 motoru Memory Heap ve Call Stack adında iki ana bileşenden oluşur. Call Stack (Çağrı Yığını) JavaScript motoru yürütme bağlamlarını (execution context) yönetmek için bir çağrı yığını kullanır. Çağrı yığını, yürütmenin devam edeceği adresi ve her çağrıdan var ise yerel değişkenleri ve parametreleri içeren bir s on giren ilk çıkar (LIFO) veri yapısıdır. Yığın (Stack) aynı zamanda JavaScript’in ilkel veri türlerini (Primitive types) depolamak için kullandığı bir yerdir. İlkel veri tiplerine string, number, undefined ve null örnek olarak gösterilebilir. İlkel veri tipleri aynı zamanda referansları da içerebilir. Referanslar ise oluşturduğunuz nesnelere ve işlevlere işaret eder. Bu verilerin boyutları sabittir ve kod yürütülmeden önce bellekte ona göre yer ayrılmıştır. Bu işleme ise ‘statik bellek ayırma (static memory allocation)’ denir. İlkel değerlerin ne kadar büyük olabileceğinin bir sınırı vardır. Bu sınır aynı şekilde yığının kendisi için de geçerlidir. Bu sınırların ne kadar olacağı kullanılan tarayıcı ve motora bağlıdır. Global execution context (GEC): Genel yürütme bağlamı (GEC), bir işlevin içerisinde olmayan tüm JavaScript kodunun yürütüldüğü varsayılan yürütme bağlamıdır. Çalıştırılan her JavaScript dosyası için yalnızca bir genel yürütme bağlamı olabilir. Function execution context (FEC): Fonksiyon çağırıldığında oluşan context türüdür. Tanımlandığında değil, çalıştığında oluşur. Örnek bir kod üzerinde inceleyelim. Adım 1: Kod belleğe yüklendiğinde, genel yürütme bağlamı (Global execution context) yığına gönderilir. Adım 2: İlk olarak “printSum()” fonksiyonu çağırılır ve bu fonksiyon yığına itilir. Adım 3: printSum fonksiyonu içerisinde toplama işlemini yapacak olan “sum()” fonksiyonu çağırılır. Bu çağrı sonucunda sum fonksiyonu da yığına itilir. Adım 4: sum fonksiyonundan dönen değer value adında bir değişkene atılır. Bu işlem sonrasında işini bitirmiş olan sum fonksiyonu yığın içerisinden kaldırılır. Adım 5: printSum fonksiyonu son olarak value değerini konsola yazdırarak yapması gereken işlemleri gerçekleştirmiş olur. Böylece printSum fonksiyonu da stack içerisinden kaldırılır. Adım 6: Program içerisinde ki tüm kodlar çalıştırılıp sona erdikten sonra genel yürütme bağlamı da (Global execution context) yığın (stack) içerisinden kaldırılır. Memory Heap (Bellek Yığını) JavaScript’in veri depolayabileceği ikinci bir yer ise bellek yığınıdır. Bellek yığını sabit miktarda yer ayırmaz. Aksine ihtiyaca yönelik miktarda yer ayırma söz konusudur. Bu işleme ‘dinamik bellek ayırma (dynamic memory allocation)’ denir. Bellek yığını içerisinde referans tipler (reference type) tutulur. Nesneler (objects) ve fonksiyonlar (functions) referans tiplere örnek olarak gösterilebilir. Peki biz bir değişken oluşturduğumuzda ne olur? İlk örnekte string değere ait değişken oluşturup bunu farklı bir değişkene kopyalıyorum. Bu şekilde bir yapı için stack resimdeki gibi davranıyor. Sonrasında ikinci oluşturmuş olduğum değişkenin değerini değiştirerek çıktısını konsolda yazdırıyorum. Stack ilk resimde birinci değişkenin adresini gösteriyorken, ikinci resimde kendine yeni bir adres oluşturdu. Bunun sebebi ilkel tiplerin (primitives type) değerlerinin değiştirilemez (immutable) olmasıdır. Bir örnekte nesneler üzerinde yapalım ve referans tiplerin bu durumda nasıl davrandığına bir göz atalım. Aynı şekilde iki adet değişken oluşturdum ve ikinci değişkenimin değeri birinci değişkenim. İlkel tipler nesneleri değer olarak tutamadıkları için nesnenin tutulduğu adresi değer olarak tutuyor. Bu örnek için ise stack ve heap resimdeki gibi davranıyor. Şimdi ikinci değişkenimin içerisinden bir değeri değiştirmek istediğimde yığından farklı olarak yığın içerisinde ki değeri değil, heap içerisinde ki değeri değiştirmiş oluyorum. Böylece çıktım iki değer için de aynı oluyor. Ben örneği her ne kadar değer güncelleme üzerinden göstersem de değişiklikler heap üzerinden yapıldığı için nesne içerisine yeni bir değer ekleme ve olan bir değeri silme işlemlerinde de süreç aynı şekilde ilerliyor. Kısaca stack ve heap üzerinde hangi değerlerin nasıl tutulduğunu; bu değerleri farklı bir değişkene atayıp, atadığımız bu değişken üzerinde değişiklik yaptığımızda nasıl davrandıklarını kabaca incelemiş olduk. Elbette çok derin bir konu olduğu için tek bir makaleyle tüm detaylarını anlatmak pek mümkün değil. Okurken merak uyandıracak bazı konular var. Örneğin; Yığının belirli bir sınırı olduğu ve ondan fazla büyüyemediğinden bahsettik. Peki o sınıra ulaşırsa ne olur? Aynı şekilde yığın içerisinde tutulan bir değerin değiştirilemediğini, bizim değişiklik yaptığımız değişkenin aslında bellek üzerinde yeni bir yer tuttuğundan bahsettik. Peki bu tarz bir durumda eski değer değişmiyorsa bellek tarafında tutulmaya devam mı ediyor? Bu soruları cevaplandırmak istediğimizde ise karşımıza Stack Overflow ve Garbage Collection kavramları çıkıyor. Okuduğunuz için teşekkürler 🥳 Kaynaklar: - https://en.wikipedia.org/wiki/V8_engine - https://developer.mozilla.org/en-US/docs/Glossary/Call_stack - https://www.javascripttutorial.net/javascript-call-stack/ - https://www.geeksforgeeks.org/memory-management-in-javascript/ JavaScript Engine, Stack — Heap was originally published in FowApps on Medium, where people are continuing the conversation by highlighting and responding to this story.