Aklımda Kalası Kelimeler

* давайте работать вместе
* Zarf ve Mazruf, Zerafet(xHoyratlık) ile aynı kökten(za-ra-fe) gelir
* Bedesten
* Suç subuta ermiştir - Suç sabit olmuştur

16 Ağustos 2018 Perşembe

SQL Server ve Linked Server

Sizin geliştirme yaptığınız makinenizde SQL Sunucu kurulmuş olsun.
Sizin ulaşabildiğiniz 2 farklı SQL sunucu daha olsun.
Bu harici 2 sunucudaki verileri kıyaslamak istiyor, yahut birindeki bilgileri diğerinde güncellemek istiyor olun.
Kendi sunucunuza SQL Management Studio ile bağlanın. Server Objects altındaki Linked Server ikonuna sağ tuş ve New Linked Server diyerek birinci sunucunuzu tanımlayın:


OPENQUERY ile sorgu yazabileceğim gibi normal bir nesneye erişir gibi de sorgu yazabilirim:

17 Ekim 2017 Salı

Redis 3.0 msi dosyasını windowsa yüklerken servis yüklenemedi hatası

İndirdiğim dosya Redis-x64-3.2.100.msi yüklerken aşağıdaki servisin yüklenmesi sırasında sürekli yeterli yetkin yok hatasını aldım. En temizinde command prompt ekranını administrator yetkisiyle sağ tuşla açtıktan sonra Redis-x64-3.2.100.msi dosyasını çalıştırdım ve bingo

18 Eylül 2017 Pazartesi

TDD

Firstly, Test Driven Development (TDD) which is a process of writing tests before writing code and make the test fail. Now write enough code so that test can pass and then at last refactor the code as per you requirement and make sure the test is passing again after the change. Now, the main focus of TDD will be on testing the low-level functionality and units (for single classes and methods) that can lead to more flexible code and easier refactoring. In a simple language we can say, we write these tests to check if the code we wrote works fine.
  1. Write just enough code so it runs
    • Create interfaces for arithmetic operations
      İlk adım olarak, test etmek isteyeceğimiz metotları içeren arayüz tiplerini oluşturuyoruz. Bu sayede kodumuz esnetilebilir bir yapıyla doğacak ve ileride concrete sınıflara değil bu arayüzlere bağımlı olacağı için işleyişi sağlayan kodumuzu dilediğimizde değiştirebileceğiz. Bu sayede sadece gerekli metotları içeren ve arayüze bağlı sınıfları kullanabileceğiz.
    • Create a class to implement those interfaces İkinci adımda concrete class yaratarak bu arayüzü miras alacak ve esas işi yapacak kodumuzu bu sınıfın metotlarına giydireceğiz.
  2. Think through how to test the code
  3. Write test cases
    Artık sınıflarınızın metotlarını(en küçük birimlerini -birim test-) test edebilecek metotları yazıyor ve testi başarıncaya kadar yani beklediğiniz sonucu alıncaya kadar sınıflarınızın metotlarını tekrar tekrar yazıyorsunuz.
    ref: https://youtu.be/2Ekty7t621k?t=4m48s
  4. Write code until test cases pass
  5. ref:https://www.youtube.com/watch?v=2Ekty7t621k

ATDD

ATDD is a collaborative exercise that involves product owners, business analysts, testers, and developers. ATDD helps to ensure that all project members understand precisely what needs to be done and implemented.
Buna en güzel örnek selenium ile yazdığınız ya da firefox eklentisi üstünden tasarlayıp azıcık kodla süslediğiniz testi örnek verebilirim.

BDD

BDD focuses on the behaviors of your system exhibits than the implementation details of it.

The focus of BDD is the language and interactions used in the process of software development. Behavior-driven developers use their native language in combination with the language of Domain Driven Design to describe the purpose and benefit of their code. This allows the developers to focus on “Does my code do what it’s supposed to do?” in addition to “Does my code work?”
Mocha ile yazdığımız testleri BDD örneği olarak bulabilirsiniz. Daha konuşma diline uygun biraz daha birim testlerin kümesi olan test türüdür.

Ref: https://www.linkedin.com/pulse/agile-development-difference-between-tddatddbdd-komal-sureka

DDD

DDD stands for Domain Driven Design. Is a way to design complex system by creating models and sub models of the domain that the system tries to implement. In the though process it means to understand the big picture, decompose it, and understand the relationships between the parts. The benefit is that it facilitates the creation of well cohesive systems.

Alan güdümlü tasarım olarak çevirebiliriz. Buradaki alan müşterinin ihtiyaçlarını ve çalışma ortamını kapsayan daire olsun. Yazılacak programın çözmesi gereken soruna problem alanı denir. Yazılımcı müşteriyle konuşurken onun ihtiyaç ve isteklerine uygun(problem domainine uygun) bir Domain Model çıkarır. Bu domain model gerçek senaryolarla denenir ve tüm sürece uygun hale getirilinceye kadar tekrar oluştururlur. Bu özyinelemeli süreç DDD'nin yazılım geliştirme yaklaşımıdır.

Ref: linkedin-Jorge Varas
youtube.com
flowframework.readthedocs.io

FDD

FEATURE DRIVEN DEVELOPMENT METHODOLOGY

Ref: http://thedynamicdomain.com/feature-driven-development.aspx

LEAN

In a nutshell, Lean says to relentlessly eliminate anything that isn’t adding value and only work on what we absolutely need to be doing at this moment in time. Eliminating waste means eliminating useless meetings, tasks and documentation. But it also means eliminating time spent building what “we know” we’ll need in the future (things are constantly changing so we often end up not needing them – or if we do, we have to rework them because conditions and our understanding has changed by then). It also means eliminating inefficient ways of working – like multitasking (!) – so we can deliver fast.
  1. Eliminate Waste
  2. Build Quality In
  3. Create Knowledge
  4. Defer Commitment
  5. Deliver Fast
  6. Respect People
  7. Optimize the Whole

AGILE

  1. Highest priority is customer satisfaction
  2. Welcome changing requirements
  3. Frequent delivery of software
  4. Business people & developers cooperating daily
  5. Build projects around motivated people
  6. Face-to-face conversation is best
  7. Progress measured by working software
  8. Sustainable development pace
  9. Continuous attention to technical excellence
  10. Simplicity
  11. Self-organizing teams
  12. Regular reflection & adaptation

Ref: https://hackerchick.com/agile-vs-lean-yeah-yeah-whats-the-difference/

2 Mayıs 2017 Salı

Unit Test mesajı görüntüleme

using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Test.FMC.Turkiye.Wcf.EFatura.WCFInvoice;
using System.Windows.Forms;
namespace Test.FMC.Turkiye.Wcf.EFatura {
    [TestClass]
    public class FEInvoiceTest {
        public TestContext TestContext { get; set; }
        static FEInvoiceClient clnt = null;
        [TestInitialize]
        public void Initialize() { clnt = new WCFInvoice.FEInvoiceClient(); }

        [TestCleanup]
        public void Cleanup() { clnt.Close(); clnt = null; }

        [TestMethod]
        public void CreateFEInvoiceClient() {
            var sonuc = clnt.Hello();

            Debug.WriteLine($"Debug mesaj: {sonuc}");
            Console.WriteLine($"Console mesaj: {sonuc}");
            Trace.WriteLine($"Trace mesaj: {sonuc}");
            TestContext.WriteLine($"TestContext mesaj: {sonuc}");
            MessageBox.Show(sonuc);
            Assert.IsTrue(!string.IsNullOrEmpty(sonuc), "Hello çağırılamadı!");
        }
    }
}

28 Nisan 2017 Cuma

Form serileştirme

Form içerisinde n tane element olan bir yapı. Form içinde topladığınız bilgileri sunucuya taşıyabilmek için HTTP paketleri kullanıyoruz. Buraya kadar hepimiz biliyoruz ;)
Bu paket başlık ve gövdeden oluşuyor ve aralarında sadece boş bir satır var. Genelde verileri gövde kısmına yükleriz. Sunucunun bu verileri parçalara ayırabilmesi(parse edebilmesi) gerekiyor. Bunu yapsın diye gövdeye yazacağımız bilgiyi iki tarafında (istemci ve sunucu) anlayabileceği şekilde oluşturmamız gerekiyor ki buna mesajın biçimi(formatı) diyoruz.
Mesaj formatlarımız neler:
  • XML
  • JSON
  • x-www-form-urlencoded
  • SOAP
  • multipart/form-data


application/x-www-form-urlencoded yapılan talebe text/html tipinde aldığımız cevap:

Encode ve Decode terimleri hep oldu hep olacak çünkü biz harf yazıyoruz ve bunu bilgisayara manyetik değer olarak kaydediyoruz. Ben bilgiyi dairesel ve çizgisel karakterler olarak ekranda görünecek şekilde kaydediyorum bir başkası video da havanın bükülerek ses dalgaları haline getirerek aktarıyor. Demek ki biz mesajları sürekli encode ediyoruz ve o mesajları okurken, dinlerken decode ediyoruz.

isim="Cem Topkaya" verisini internet ortamında transfer etmek için url'nin sonuna eklediğimizi düşünelim http://cemtopkaya.com/kullanici.php?isim=Cem Topkaya siz de farkettinizki soyisim bir boşlukla ayrıldığı için url'nin parçası olamıyor.

26 Nisan 2017 Çarşamba

Typescript kodunda async, await, promise, bulebird ve q ile Redis işlemlerini yönetmek

Adım adım anlatabilmek isterdim ama vaktim az olduğu için sadece kodu paylaşmakla yetineceğim şimdilik.
Sadece şunu söyleyerek anlatımı bitirip sizi kodla başbaşa bırakacağım:
İşin öğrenme sırası şöyle olmalı:
0. Asenkron ve senkron işlemler
1. Callback pattern
2. Promise (ecmascript 6 ile gelen Promise yapısı ve bunun öncülleri çatılar)
3. async ve await

2 için bluebird, kriskovalQ işlerini biraz öğrendikten sonra aşağıdaki örnek kolaylıkla anlaşılabilecektir.
Vakit bulunca anlatımı daha genişletmek ümidiyle.

import { RedisClient, createClient, ClientOpts } from "redis";
import { promisifyAll, PromisifyAllOptions } from "bluebird";
import { nbind } from "Q";

export module FMC_Redis {
    export class Redis {
        opt: ClientOpts;
        private rc: RedisClient;
        private rcPromise: any;

        private static _instance: Redis = null;
        public static current(_opt?: ClientOpts): Redis {

            if (!Redis._instance) {
                Redis._instance = new Redis(_opt);
                Redis._instance.redisConnect();
            }
            return Redis._instance;
        }

        public get client(): RedisClient {
            if (!this.rc.connected) throw new Error("There is no connection to Redis DB!");
            return this.rc;
        }

        /******* BLUEBIRD ********/
        public get clientAsync(): any {
            // promisifyAll functions of redisClient 
            // creating new redis client object which contains xxxAsync(..) functions.
            return this.rcPromise = promisifyAll(this.client);
        }

        private constructor(_opt?: ClientOpts) {
            if (Redis._instance) return;

            this.opt = _opt
                ? _opt
                : {
                    host: "127.0.0.1",
                    port: 6379,
                    db: "0"
                };
        }

        public redisConnect(): void {
            this.rc = createClient(this.opt);
            this.rc
                .on("ready", this.onReady)
                .on("end", this.onEnd)
                .on("error", this.onError);
        }

        private onReady(): void { console.log("Redis connection was successfully established." + arguments); }
        private onEnd(): void { console.warn("Redis connection was closed."); }
        private onError(err: any): void { console.error("There is an error: " + err); }


        /****** PROMISE *********/
        // promise redis test
        public getRegularPromise() {
            let rc = this.client;
            return new Promise(function (res, rej) {
                console.warn("> getKeyPromise() ::");
                rc.get("cem", function (err, val) {
                    console.log("DB Response OK.");
                    // if DB generated error:
                    if (err) rej(err);
                    // DB generated result:
                    else res(val);
                });
            });
        }


        /******* ASYNC - AWAIT *******/
        // async - await test function
        public delay(ms) {
            return new Promise((fnResolve, fnReject) => {
                setTimeout(fnResolve("> delay(" + ms + ") > successfull result"), ms);
            });
        }

        public async delayTest() {
            console.log("\n****** delayTest ")
            let a = this.delay(500).then(a => console.log("\t" + a));

            let b: string = await this.delay(400);
            console.log("\tb::: " + b);
        }

        // async - await function
        public async getKey(key: string) {
            let reply = await this.clientAsync.getAsync("cem");
            return reply.toString();
        }

        Get: (...args: any[]) => Q.Promise<{}>;
        // Q
        public nbind() {
            this.Get = nbind(this.client.get, this.client);
        }

    }
}

let a = FMC_Redis.Redis.current();

// setTimeout(function () {
//     console.warn(a.client.set("cem", "naber"));
//     console.warn(a.client.get("cem"));
//     console.warn(a.client.keys("cem"));
// }, 1000);

/***** async await test client *****/
a.delayTest();


/** Standart Redis Client test client */
setTimeout(function () {
    a.client.get("cem", function (err, val) {
        console.log("\n****** Standart Redis Client")
        if (err) console.error("\tError: " + err);
        else console.log("\tValue ::" + val);
    });
}, 100)

/***** Using regular Promise with Redis Client > test client *****/
setTimeout(function () {
    a.getRegularPromise().then(function (v) {
        console.log("\n***** Regular Promise with Redis Client")
        console.log("\t> Then ::" + v);
    }).catch(function (e) {
        console.error("\t> Catch ::" + e);
    });
}, 100);

/***** Using bluebird promisify with Redis Client > test client *****/
setTimeout(function () {
    var header = "\n***** bluebird promisify with Redis Client";
    a.clientAsync.getAsync("cem").then(result => console.log(header + result)).catch(console.error);
}, 100);

// a.delay(2000).then((v) => {
//     console.error("then oldu");
//     a.promisify();
//     a.getKey("cem").then(console.log);
// });

    console.log("haydaaaa");

setTimeout(async function () {
    console.log("haydaaaa");
    a.nbind();
    let k = await a.Get("cem");
    console.log("K: " + k);
}, 100);

Bu güzel bir adres async await için: https://blog.mariusschulz.com/2016/12/09/typescript-2-1-async-await-for-es3-es5
Promise kısmını anlamak için bu güzel: https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
Bu da fena değil: https://blogs.msdn.microsoft.com/typescript/2016/11/08/typescript-2-1-rc-better-inference-async-functions-and-more/

14 Mart 2017 Salı

Typescript notlarım

Functions are first class objects in javascript

JS de fonksiyonlar birinci sınıf nesnelerdir (Functions are first class objects in javascript). Yani javascript fonksiyonlar, nesnenin özel tipli halleridir. Bir fonksiyon köken itibarıyla nesnedir aynı zamanda.
Fonksiyonlar sadece bir metot değil, aynı zamanda veri tutan, nesne yaratılan, statik metot ve verileri olan sınıflardır.
function Deneme(parametreVeri){ 
  
  this.NesneVerisi = parametreVeri;

  this.NesneyeBagliMetot = function() {
    console.log("Nesne tarafından çağırılabilir");
  }

}

Deneme.StatikVeri = "Sadece fonksiyon adından erişilebilir";

Deneme.StatikMetot = function() { 
  console.log("Sadece fonksiyon üstünden çağırılabilen metot");
};

Deneme.prototype.NesneyeBagliMetot2 = function() {
  // Tüm nesneler, Deneme fonksiyonunun prototype özelliğine
  // erişebildiği için bu tip metot ve özellikler bir kez yaratılır
  // ve Deneme sınıfından yaratılmış tüm nesneler tarafından kullanılır
  console.log("this ile nesneye erişiriz: " + this.NesneVerisi);
};

Deneme.prototype.NesneyeBagliVeri2 = "Bu şekilde de nesneye veri eklenebilir";

console.dir(Deneme)

18 Şubat 2017 Cumartesi

2 Şubat 2017 Perşembe

PM2 Notlarım

pm2 ecosystem ile birden fazla uygulamanın ayarlarını yapabileceğiniz bir dosya yaratın ve oluşan dosyanın içeriğini değiştirerek istediğiniz aşamaya getirin. Benim örneğim şu:
module.exports = {
    /**
     * Application configuration section
     * http://pm2.keymetrics.io/docs/usage/application-declaration/
     */
    apps: [

        // kuark application
        {
            name: "kuark-www",
            script: "./App/www.js",
            exec_mode: "cluster",
            instances: "1",
            env: {
                COMMON_VARIABLE: "true"
            },
            env_production: {
                NODE_ENV: "production"
            }
        },

        // Redis application
        {
            name: "redis-batch",
            script: "./Apps/Batch_Redis/index.js",
            exec_mode: "cluster",
            instances: "1"
        },

        // Elastic application
        {
            name: "elastic-batch",
            script: "./Apps/Batch_Elastic/index.js",
            exec_mode: "cluster",
            instances: "1"
        }
    ],

    /**
     * Bu kısmı henüz kullanmadım
     */
    deploy: {
        production: {
            user: "node",
            host: "212.83.163.1",
            ref: "origin/master",
            repo: "git@github.com:repo.git",
            path: "/var/www/production",
            "post-deploy": "npm install && pm2 startOrRestart ecosystem.json --env production"
        },
        dev: {
            user: "node",
            host: "212.83.163.1",
            ref: "origin/master",
            repo: "git@github.com:repo.git",
            path: "/var/www/development",
            "post-deploy": "npm install && pm2 startOrRestart ecosystem.json --env dev",
            env: {
                NODE_ENV: "dev"
            }
        }
    }
}

Klasörde ilgili dizine gelerek pm2 starOrReload ecosystem.json ile başlatabilirsiniz.
Linux'te otomatik başlatma nasıl olur diye aradım bunu buldum ama o sistemi tam anladıktan sonra detaylandıracağım inşallahhhhhhhhhhhhhh

Temel pm2 parametrelerini aşağıda ekliyorum ama npm den çektim buda böyle biline :)
# General
$ npm install pm2 -g            # Install PM2
$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)
$ pm2 start npm -- start        # Start, Daemonize and auto-restart Node application
 
# Cluster Mode (Node.js only)
$ pm2 start app.js -i 4         # Start 4 instances of application in cluster mode
                                # it will load balance network queries to each app
$ pm2 reload all                # Zero Second Downtime Reload
$ pm2 scale [app-name] 10       # Scale Cluster app to 10 process
 
# Process Monitoring
$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application
 
# Log management
$ pm2 logs                      # Display logs of all apps
$ pm2 logs [app-name]           # Display logs for a specific app
$ pm2 logs --json               # Logs in JSON format
$ pm2 flush
$ pm2 reloadLogs
 
# Process State Management
$ pm2 start app.js --name="api" # Start application and name it "api"
$ pm2 start app.js -- -a 34     # Start app and pass option "-a 34" as argument
$ pm2 start app.js --watch      # Restart application on file change
$ pm2 start script.sh           # Start bash script
$ pm2 start app.json            # Start all applications declared in app.json
$ pm2 reset [app-name]          # Reset all counters
$ pm2 stop all                  # Stop all apps
$ pm2 stop 0                    # Stop process with id 0
$ pm2 restart all               # Restart all apps
$ pm2 gracefulReload all        # Graceful reload all apps in cluster mode
$ pm2 delete all                # Kill and delete all apps
$ pm2 delete 0                  # Delete app with id 0
 
# Startup/Boot management
$ pm2 startup                   # Detect init system, generate and configure pm2 boot on startup
$ pm2 save                      # Save current process list
$ pm2 resurrect                 # Restore previously save processes
$ pm2 unstartup                 # Disable and remove startup system
 
$ pm2 update                    # Save processes, kill PM2 and restore processes
$ pm2 generate                  # Generate a sample json configuration file
 
# Deployment
$ pm2 deploy app.json prod setup    # Setup "prod" remote server
$ pm2 deploy app.json prod          # Update "prod" remote server
$ pm2 deploy app.json prod revert 2 # Revert "prod" remote server by 2
 
# Module system
$ pm2 module:generate [name]    # Generate sample module with name [name]
$ pm2 install pm2-logrotate     # Install module (here a log rotation system)
$ pm2 uninstall pm2-logrotate   # Uninstall module
$ pm2 publish                   # Increment version, git push and npm publish

5 Ocak 2017 Perşembe


- N-Tier uygulamaların gelişimi
- Data-Centric N-Tier mimari
- Domain-Centric N-Tier mimari

N-Tier Uygulamalar

- N-Tier tanımlamak
- Logical - Physical Seperation
- Typical Tiers

Tier ve Layer Nedir?

LAyer, mantıksal ayrım olup Tier ise fiziksel ayrım için kullanılır.
Örneğin programınızı yazarken UI(Kullanıcı Arayüz) katmanı, BUSINESS(İŞ) katmanı ve DATA(Veri) katmanı olarak 3 dll geliştirdiğinizi ve tüm bunları ayrı projelerde kodladığınızı düşünün. Artık 3 Layers bir uygulamanız var demektir. Layerlarınızın her birini 3 farklı makinede/sistemde barındırırsanız N-Tier ile tanımlanacak N sizin için 3 olur. Yani 3-Layers olarak geliştirdiğiniz projenizi 3-Tiers sunuyor olursunuz. Bu layer'ların 3'ünü de tek bir bilgisayarda hizmete sunuyorsanız 1 Tier'ınız oldu demektir. Yani MVC uygulamanızda M, V ve C için 3 farklı proje(namespace, assembly, SOFTWARE DESIGN PATTERN'e göre vs.) geliştirdiniz ve bu layerlarınızı tek bir IIS sunucusunda(1-Tier) barındırdınız. Uygulamanızı en basit olacak şekilde windows form olarak geliştirdiniz(tek process ya da tek assembly) ve istemciye yükleyerek çalıştırdınız 1-Layer ve 1 Tier. Uygulamanızın parçaları eğer farklı process, makine, cihaz vs de çalışıyorsa bunlar fiziksel ayrımlar olacaktır ve sebebi bu kez SOFTWARE ARCHITECTURE.

Monolithic Application

Access ile yazılmış bir uygulama monolitik olacaktır. DB ve KOD içinde ve mantıksal ya da fiziksel bir ayrım yapılamayacaktır. Aynı şekilde konsol uygulamaları da monolitiktir. Eğer fiziksel olarak bölümlere ayırmış olsaydık yani data servislerini ayrı, uygulama servisini ayrı fiziksel katmanlara ayırsaydık; ölçeklendirme, güvenlik, hata toleransı ve yük dengesini dağıtmak gibi konularda faydalar üretebilirdik.

  1. Önceleri tüm kodu tek bir assembly olarak yazar aynı makinedeki veritabanı sunucusuna bağlanarak iş yapardık.
  2. Sonra uygulama içindeki katmanları keşfettik, UI, BLL(business logic layer), DAL(data access layer).
  3. Sonra database sunucusunu ayrı bir makinede kurduk.
  4. Sonra data ve iş katmanını ayırarak bir servis içinde tutarak ayrı bir makinede tutarak farklı uygulamaların(UI katanların) uygulama servislerini(BLL, DAL) kullanarak Data Servislerine(db tier'ına) erişmelerine imkan verdik.

N-Tier ile:
  1. Tekrar kullanımları sağladık(mobil, masaüstü, browser vs. uygulama arayüzlerinin application services(BLL,DAL...) katmanlarını kullanarak arkalarındaki data services katmanlarına erişmesi gibi)
  2. Takımların ayrımlarını ve bu sayede geliştirme verimliliğini yakaladık
  3. Katmanlara bölünmüş(tier ve/veya layer) yapıların bakımı daha kolay oldu
  4. Birbirine daha esnek bağlanan yapılara sağladık (loose coupling)

End Runs'dan kaçınmak

Eğer bir katmanınız sonraki katman yerine daha ötedeki katmanları çağırıyor ya da aşağıdaki katman çok yukarıdaki katmanlara veriyi aradaki katmanları atlayarak gönderiyorsa bu yapı sorunlu olacaktır.


Data-Centric N-Tier Dizayn




IEnumerable ve IEnumerator farkları nelerdir

IEnumerable interface'i bize hangi metodu yazmayı zorlar ona bir bakalım:
public interface IEnumerable
{
  IEnumerator GetEnumerator();
}

Peki bu metodu kim çağıracakki biz implemente edelim?
foreach(var eleman in kolleksiyon)
foreach Arka tarafta şunu yaratır:
var oteleyen = kolleksiyon.GetEnumerator();
while(oteleyen.MoveNext()) // true dönerse, eleman var demektir
{
  Console.WriteLine(oteleyen.Current); // eleman'ın ToString metodunu çağır ekrana yaz
}
oteleyen.Reset(); // kolleksiyonun içinde döndük sona geldik, başa dönmek için resetleyelim

Bu da güzeldi ancak biz sadece GetEnumerator metodunu anlayalım derken başımıza MoveNext(), Current ve Reset() çıktı!!!
Peki bize bu metotları sağlayan tip kimdir?
var oteleyen = kolleksiyon.GetEnuemerator(); // aslında şöyle de yazılabilir
IEnumerator oteleyen = kolleksiyon.GetEnuemerator(); 
Demekki tipimiz IEnumerator. Peki o zaman IEnumerator bize ne şartı koşuyor içine bakalım:
public interface IEnumerator
{
  object Current { get; } // Şimdi üstünde bulunduğum elemanı ver bakalım
  bool MoveNext();        // sonraki eleman mevcut mu?
  void Reset();           // en baştaki noktaya geri gidelim
}

Anlaşıldıki bizim forEach bir IEnumerator(numaralandırıcı) istiyor ve onun nimetleri olan metot ve özelliği kullanarak kolleksiyon içinde dönüyor duruyor.
Peki bu tipin generic olması bize ne kazandırır? O zaman generic IEnumerator tipine bakalım ve casting ile kaybettiğimiz performansı bakalım nasıl geri alıyoruz?
public interface IEnumerator : IDisposable, IEnumerator
{
  T Current { get; }  
  // Sadece Current için T tipini sağlıyor. 
  // Zaten Reset void döner, MoveNext ise bool geriye performans kaybı yaşatan Current kalıyor
  // Onuda T dönecek şekle getirirsek sorun giderilmiş olur.
}

Peki GetEnumerator() metodu bize IEnumerator dönüyordu. Onu da generic ile IEnumerator dönecek şekle getirmemiz gerekmez mi?
public interface IEnumerable : IEnumerable
{
  IEnumerator GetEnumerator();
}
Şimdi tip dönüşümlerinden kurtulduğumuza göre performans rahatlığıyla bu iki tipi kullanabiliriz.
Gelin kendimize bir örnek yazalım ve makalemizi sonlandıralım. Eğer anlaşılmayan yerler olursa lütfen yorumlarınızda sorun ;)
class Cem : IEnumerable, IEnumerator
{
    T[] arr = new T[0];
    int iCur = 0;

    int idx = -1;
    public T Current
    {
        get
        {
            return arr[idx];
        }
    }

    object IEnumerator.Current
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public void Add(T a) { 
      Array.Resize(ref arr, arr.Length + 1); // dizimizi bir arttıralım ki yeni elemanı ekleyebilelim
      arr[arr.Length-1] = a; // artık bir büyüdüğüne göre -1 ile sonuncu sıraya yeni elemanı yerleştirelim
    }

    public void Dispose() { }

    public IEnumerator GetEnumerator() { return this; }

    public bool MoveNext()
    {
        var next = idx + 1;
        var sonuc = (next < arr.Length);
        if (sonuc) idx = next;
        return sonuc;
    }

    public void Reset()
    {
        idx = -1;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}
class Program
{
    static void Main(string[] args)
    {
        var c = new Cem();
        c.Add(22);
        c.Add(32);
        c.Add(42);
        c.Add(44);
        foreach (var a in c)
            Console.WriteLine(a);
    }
}

2 Ocak 2017 Pazartesi

Üçüncü şirketlerle çalışmak için yol haritası

Şirketinizde bir yazılım ihtiyacı hasıl oldu. Tabiki bunu yazabilirsiniz ama kimse sizin bu işi yapabileceğinize inanmıyor ya da daha fazla size yazdırıp şirketin size olan bağımlılığını arttırmak istemiyor.
Çözüm: gidin ve dışarıdan alın olacaktır.
  1. İhtiyacın a'dan z'ye analizini yapmalısınız. Sanki siz geliştirecekmiş gibi özenerek bir A4 sayfa koparın defterinizden ve 1, 2 diyerek madde madde yazın.
  2. Sonra kabataslak bu ihtiyacı karşılayabilecek anahtar kelimelerin olduğu google aramalarını yapın ve şirketlerin listesini çıkarın.
  3. Bu firmaları ellerindeki belgelendirmelere göre sıralayın. ISO, SPICE, CMMI vs.
  4. Sonra fiyatları almak için her biriyle görüşün ve ihtiyaçlarınızı karşılayabilecek şirketleri listenizde kalacak şekilde sıralayın.
  5. Yani Order by, [ihtiyaç karşılama oranı], [belgelelerin sayısı], fiyatı.
  6. Her zaman açık kaynak kod olmasını talep edin ki yarı yolda kalma ihtimaliniz düşük olsun.
  7. Eğer bir ihtiyacınız olacak ve yazmalarını talep edecekseniz başta rakamı belirleyin(adam/gün, ihtiyaç türleri(küçük, büyük, kocaman vs.).
  8. SLA(service level agreement) ile arıza durumlarına ne kadar zamanda çözüm üretebileceklerini, arıza kayıtlarını nasıl açmanız gerektiğini ve zamanında çözülmeyen sorunlar için yükümlülükleri sözleşmeye eklemeyi unutmayın.
  9. Sizi ilgilendiriyorsa (denetimlerden geçiyorsanız, kalite prosedürlerini varsa) kesinlikle Yazılımın Validasyon belgelendirmesini isteyin.
  10. Kurulum süreçleri hep zahmetlidir. Şifre al, şifrele, eski şifre neydi gibi bir sürü kıvır zıvır işle uğraşırsınız. Bu yüzden kurulumun bir resmi tatil günü gece yarısı sistem mühendisiniz tarafından diski bozulmuş bir makineyi tekrar ayanlandıramadığı durumlar için yapılması gerektiğini düşünmelisiniz. Kurulumun tüm aşamalarını sizinle paylaşmalılar !
  11. Bakım sözleşmesi saçmalığını artık kazan kazan sözleşmesine çevirmek gerekiyor. Bakımda neymiş yahu, diyerek her sene ödediğiniz para için size yeni sürümleri vermeliler, ekstra özellikler (x adam/gün geliştirme hediye gibi) bonusu istemelisiniz.

Ayrıca bu projeyi siz de yazabilirdiniz elbette ama bence şirketinize bu konuda ısrarcı olmayın çünkü dışarıdaki şirketler sizin gibi personellere sahip olmadıkları için maalesef ve dünyanın her yerinde pişman edeceklerdir şirketinizi :)

21 Eylül 2016 Çarşamba

Elasticsearch ve Mapping

Aşağıda ilişkisel veritabanı ile ES arasındaki terminolojik bağlantıları göreceksiniz.

Şema kavramı ile Mapping arasında terminolojik olarak aynılığı yukarıdaki resimde gördünüz.
Tablo ile Tip arasındaki aynılıkta dikkatinizi çekmiştir.
O halde ilişkisel veritabanlarında bir tablonun şeması olduğunu yani içindeki kolonların hangi tiplerde veri aldığını belirttiğinizi hatırlarsanız, şema

Mapping nedir, nasıl belirtilir, nasıl yapılandırılır ve verimize nasıl uygulanır diye bakalım.
Şema, bir ya da daha fazla alanları olan belgenin tanımıdır. ES JSON tipinde verileri muhafaza ettiğinden dolayı, JSON verisinin içinde veri tipini bu verinin nasıl indekslenmesi gerektiğini "mapping" ile belirtiriz ki mapping ES dünyasında şema demektir.
ES içinde 0 ya da daha fazla index ve bu indexler 0 veya daha fazla document içerir. Bir başka deyişle; bir belgenin bir tipe ve bir index'e bağlı tanımlayıcısı vardır.

Yukarıdaki şekilde INDEX, TIP be DOKUMAN kutularını görüyorsunuz. A,B,X ve Y belgelerinin my_type adında bir tipi ve my_index adında bir indexi var. Aynı indeksi bir başka tip olan "another_type" ve bu tipi kullanan belgeler de kullanıyor. Yukarıdaki figürdeki TIP aslında

19 Temmuz 2016 Salı

ASP.NET 5 Üzerine

ASP.NET yeni, açık kaynak kodlu ve mac, linux, windows gibi işletim sistemlerinde çalışabilen(cross-platform) çatı olarak karşımıza geliyor. Web uygulamalarızı buluta taşımak konusunda daha esnek bir yapıda en baştan tekrar geliştirildi bu çatı.
ASP.NET 5 ile birlikte gelen komut satırı araçlarıyla Visual Studio dışından cross-platform ASP.NET uygulamalarını basit bir metin editörüyle(notepad gibi) geliştirebilecek visual studio çalıştırmadan CMD ya da Poweshell(windows üstünde tabii) derleyebileceğiz. Bu komutlar ASP.NET 5 içinde
  1. DNX (.Net Execution Environment-.Net çalıştırma ortamı) .NET 5 uygulamalarının ihtiyaç duyacağı bileşenleri içeren, eski usül .net çatısı olup içinde birden fazla .net versiyonunu içerebilmesi sayesinde dll cehennemini yaşamamızı sağlar,
  2. DNVM(.Net Version Manager) ile hangi DNX sürümünü kullanacağımızı seçeriz,
  3. DNU (DNX klasöründe bulunan DNU kütüphanesi sayesinde .NET 5 uyugulamasının project.json içinde tanımlanmış ihtiyaç duyacağı paketlerin yönetilmesini -yükleme(installation) veya geri yükleme(restoring)- sağlar.),

1 Temmuz 2016 Cuma

Pair Programming üzerine

Ne zaman roller değişmeli:

Diyelimki 4 takımın var ve elbette ikişer kişiden oluşuyor. Periyodik olarak takım üyelerinin yerlerini değiştirmek iyidir, candır.

19 Mart 2016 Cumartesi

npm ayarları

NPM SET INIT


NPM addUser

npm client için www.npmjs.com adresinde kayıtlı olan kullanıcı bilgilerinizi bir kerede girmeniz ve ileride gerekmemesi için gerekli ayarlar:


.gitignore Dosyasıyla Yoksayılacaklar


git add -A

Tüm dosyaları (.gitignore içinde olmayan tüm dosyaları) repository'e gönderecek şekilde işaretler.

git commit -m "mesajınız"

Yaptığınız değişiklikleri bir mesaj ile repoya gönderilecek şekilde işaretler

git push

Artık github'a gittiler git push ile.

npm publish

github üstünde artık kodlarınız bulunuyor ancak npm install paket_adi ile indirilebilimesi için npmjs.com adresine publish edilmesi gerekiyor.

git tag

Buraya kadar kodunuzu ilk kez git's yüklediniz ve npm paketinizi kayıt ettirdiniz. artık npm install paketinizin_adi diyerek kullandırabilirsiniz ama zaman içinde çeşitli sürümler yaparak hem eski sürümlerinize erişim hem de yenilerini kullanma imkanı sunmak istiyorsunuz. O halde git tag [versiyonNo] ile sürekli sürüm yapabilirsiniz git üstünde. Tabi bunları npm tarafında da güncel tutmanız gerekecek ama önce git etiketlemesine bakalım:
Artık github üstünde versiyonNo etiketli sürümünüzü görebilir buna bir başlık açabilir üstünden sorunları giderebilirsiniz.

Artık Yeni Sürüm


npm install

npm install paketAdi             // son stabil paketi
npm install paketAdi@beta        // son beta sürümünü
npm install paketAdi@versiyonNo  // son beta sürümünü


npm version patch

Sadece package.json içindeki sürüm bilgisinin patch sayısını bir arttırıp package.json içindeki bilgiyi güncelleyecektir. Tabii bu işi git üstünden yaptığı için (git içindeki git-tag-version ile) git versiyonu da değişecektir. Bunu git üstünden yapmamak için npm --no-git-tag-version version -f çalıştırmalısınız.
npm version major|minor|patch şeklinde çeşitlerini buradan bulabilirsin.

npm scripts

Ref: http://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm
Bir versiyon temel olarak major.minor.patch bölümlerinden oluşur.
Yamalamak için versiyonlama işi kısaca npm version patch ile olabilir ancak bu versiyonu npmjs.com adresine publish etmek içinde npm publish demek gerekecektir. Bunu otomatik hale getirmek için aşağıdaki blok iş görecektir. npm run patch-release ile tümünü tek bir kod ile yapabilirsiniz.
#package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "patch-release": "npm version patch && npm publish && git push --follow-tags"
  }
}

Daha karmaşık bir yapıyı parçalara bölerek oluşturup tek elden çalıştırbilirsiniz npm run deploy ile.
"scripts": {
    "build": "...",
    "git-commit": "git add -A . && git commit -a -m 'gh-pages update'",
    "git-push": "git push origin gh-pages --force && git checkout master",
    "deploy": "npm run build && npm run git-commit && npm run git-push"
  },

git config --global credential.helper wincred

Git hesabınızı windows komut satırında kullanırken defalarca kullanıcı adınızın sorulmasını istemezseniz komut satırına
$ git config --global credential.helper wincred
yazmanız halinde artık kullanıcı bilgilerinizi windows tutacaktır. Yapmanız gereken git depolarından bir kaynak kodunuzla ilgili güncelleme yaparken bir kez kullanıcı adı ve şifrenizi girmek olacaktır. git config --list ile ayarlarınıza baktığınızda credential.helper=wincred satırını göreceksiniz ve sonraki tüm git işlemlerinizi komut satırından yaparken size kullanıcı adı ve şifresi sormayacak.

Windows credentials ile baktığınızda "Generic Credentials" kısmında github şifrenizin depolandığını göreceksiniz.

git config --list


cem.topkaya@CZC11141WZ C:\_Projeler\Cop\modules\kuark-istisna
$ git config --list
core.symlinks=false
core.autocrlf=false
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
pack.packsizelimit=2g
help.format=html
http.sslcainfo=/bin/curl-ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
diff.astextplain.textconv=astextplain
rebase.autosquash=true
user.name=cemtopkaya
user.email=cem.topkaya@hotmail.com
gui.recentrepo=C:/Users/cem.topkaya/Documents/Visual Studio 2013/Projects/ConsoleApplication8/CSharp_Orneklerim_Git
credential.helper=wincred
http.postbuffer=524288000
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
core.hidedotfiles=dotGitOnly
remote.origin.url=https://github.com/cemtopkaya/repo-adi.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

cem.topkaya@CZC11141WZ C:\_Projeler\Cop\modules\kuark-istisna

git config --global push.default matching

Daha sade bir çıktı almak istersek kullanacağız. Yani, normalde $ git push aşağıdaki çıtıyı veriyorken:
$ git config --global push.default matching
Komutunu çalıştırarak sadece şu çıktıyı alıyoruz:

Bu çıktıyı şu config listelerindeki değişimlerde görelim:


20 Ocak 2016 Çarşamba

Linq ile GroupBy ve Sum örneği

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication6
{
    class Tax
    {
        public int Orani;
        public int Amount;
        public int ReasonCode;
        public string Reason;
        public override string ToString()
        {
            return string.Format("Oranı:{0}, Amount:{1}, ReasonCode:{2}, Reason:{3}", Orani,Amount,ReasonCode,Reason);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            List lst = new List()
                            {
                                new Tax(){Amount = 10, Orani = 18},
                                new Tax(){Amount = 5, Orani = 18},
                                new Tax(){Amount = 0, Orani = 0, Reason = "351", ReasonCode = 351},
                                new Tax(){Amount = 0, Orani = 0, Reason = "251", ReasonCode = 251},
                                new Tax(){Amount = 6, Orani = 8},
                                new Tax(){Amount = 16, Orani = 8},
                            };
            // Sum Amount
            var total = (from l in lst
                select l.Amount).Sum();
            Console.WriteLine("Toplam Vergi: "+total);

            // GroupBy
            var a = from l in lst
                group l by l.Orani
                into g
                orderby g.Key
                select g;
            foreach (IGrouping g in a)
            {
                Console.WriteLine(g.Key);
                foreach (Tax tax in g)
                {
                    Console.WriteLine(tax);
                }
            }
        }
    }
}
Çıktısı:

7 Ocak 2016 Perşembe

Dosyayı, sunucudaki adından farklı kaydetmek

Amacım DWelle RSS'indeki Almanca mp3 eğitim dosyalarını eğitimin başlığıyla kaydetmek. Elimizdekiler:
Öncelikle mp3 dosyalarına tıkladığımızda kaydetmek için karşımıza gelecek dosya adı şöyle gözüküyor:
Biz ise kaydederken adının title alanına ".mp3" eklenmiş halini Ders 10 - Bir oda rezervasyonu yaptırmak istiyorum.mp3 istiyoruz. Eğer a etiketi içinde href özelliği bir adresi değilde doğrudan dosyayı içeriyor olsaydı kaydetmek için istediğimiz dosya adını download özelliğine yazmamız ve tıklamamız yeterliydi. <a download="logo.png" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">Download transparent png</a> RSS içindeki bilgileri çekmek için XPath kullanabilirsiniz. Bunu da Chrome browser ile yapabilirsiniz. Güzel bir anlatım için aşağıdaki resimlere bakabilirsiniz:
Kaynak: http://yizeng.me/2014/03/23/evaluate-and-validate-xpath-css-selectors-in-chrome-developer-tools/ Bizim a etiketlerimiz şöyle olacak:
<a href='http://radio-download.dw.de/Events/podcasts/tur/3803_DKpodcast_dwn1_tur/DWN_Tuerkisch_Serie1_Lektion01-podcast-3803-293588.mp3' data-saveas='Ders 01 - Bu bir şarkı.mp3'>Ders 01 - Bu bir şarkı</a>
data-saveas içinde yeni dosya adı, href içinde ise sunucudaki dosyanın adresini tutacağız. Haydi başlayalım ! Aşağıdaki kodu Chrom'un Console sekmesinde çalıştırdığınızda xpath ile sogulamalar için hızlı ve manipule edebileceğiniz bir fonksiyonu yüklemiş olursunuz.
var xpath = function(xpathToExecute){
  var result = [];
  var nodesSnapshot = document.evaluate(xpathToExecute, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
  for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ ){
    result.push( nodesSnapshot.snapshotItem(i) );
  }
  return result;
}
Bu kod ile indirilecek a etiketlerini oluşturalım
var aDizi = [], 
    arrTitle= xpath("//item/title/text()"), // Tüm title içindekilerini alalım. Bunlar bizim mp3 dosyamızı kaydederken kullanacağımız dosya adlarımız olacak
    arrUrl=xpath("//item/enclosure/@url/text()");// Tüm mp3 dosyalarının URL adreslerini alalım. Önce stream olarak alıp blob olarak saklayacak ve tıkladığımız a etiketlerinden diskimize kaydedeceğimiz akışlar

arrTitle.forEach(function(_title, _idx){
  console.log(_idx)
  console.log(arrUrl[_idx])
  aDizi.push("<a href='"+arrUrl[_idx].value+"'>"+_title+"</a>");
})
console.log(aDizi); // Ekranda görelimki listeyi kopyalayıp html dosyamıza yapıştırarak indireceğiz
jQuery candır. Onu sayfamıza bir ekleyelim.
<html>
<head>
    <script src=http://code.jquery.com/jquery-2.1.4.min.js></script>
Sayfamızda data-saveas propertysi olan a etiketlerinin üstünden geçerek href özelliklerindeki adresten akışı indireceğiz ve Blob'a yazarak tekrar a etiketine bağlayacağız.
    <script type=text/javascript>
        $(function() {
            // iterate over all the items that are marked as saveas
            $('a[data-saveas]').each(function() {
                var $this = $(this);

                // İndirmek istediğimiz adres ve diske hangi isimle kaydetmek istiyorsak, yeni dosya adı
                var target = $this.prop('href'),
                    saveas = $this.data('saveas');

                // kaynaktan dosyayı indirmek için ajax kullanacağız
                $.ajax({
                    url: target,
                    type: 'GET',
                    mimeType: 'text/plain; charset=x-user-defined', 
                    error: function(a, b, c, d) {
                        debugger;
                    }
                }).done(function(data, textStatus, jqXHR) {

                    // VERİYİ ÇEKTİK VE ŞİMDİ BLOB OLARAK SAKLAYACAĞIZ
                    var bufferBos = new Int8Array(new ArrayBuffer(data.length));
                    for (var i = 0; i < data.length; i++) {
                        var charCode = data.charCodeAt(i); // ascii
                        bufferBos[i] = charCode; // gelen her byte'ı 8 bitlik(octet) elemanlar olarak diziye yerleştirelim
                    }
                    // Blob oluşturmak yapıcı olarak veriyi ve verinin tipini vermemiz gerekiyor
                    // new Blob([bufferlanmış veri], { type: mimeString })
                    var mimeString = jqXHR.getResponseHeader('Content-Type');
                    var blob = new Blob([bufferBos], { type: mimeString });


                    // ŞİMDİ DEFAULT HREF BİLGİLERİNE GÖRE KAYDETMEMEK İÇİN DÜZENLEYELİM
                    // Blob içine kaydettiğimiz veriye erişebilmek için URL oluşturacağız.
                    var href = (window.webkitURL || window.URL).createObjectURL(blob);
                    $this.prop({
                        // Tıklandığında download propertysinden yer alan ad ile kaydedecek
                        'download': saveas,
                        'href': href,
                        'draggable': true
                    }).data({
                        // <a href="#" class="dnd" data-downloadurl="MIME_Type:File_Name:Blob_URL"></a>
                        // Örneğin:
                        // <a href="#" class="dnd" data-downloadurl="image/jpeg:Penguins.jpg:https://www.box.net/box_download_file?file_id=f66690"></a>
                        'downloadurl': [mimeString, saveas, href].join(':')
                    });
                });
            });
        });
    </script>
</head>
HTML dosyamıza bağlantılarımızı da ekleyerek tamamlayalım. Sayfa yüklendiğinde tüm a elemanlarının içinde dolaşarak ilgili dosyaları blob halinde browser'da tutacak ve tıkladığımızda belirttiğimiz dosya adıyla kaydetmiş olacağız.
<body>
    0: <a href='http://radio-download.dw.de/Events/podcasts/tur/3803_DKpodcast_dwn1_tur/DWN_Tuerkisch_Serie1_Lektion01-podcast-3803-293588.mp3' data-saveas='Ders 01 - Bu bir şarkı.mp3'>Ders 01 - Bu bir şarkı</a>
    <br />1: <a href='http://radio-download.dw.de/Events/podcasts/tur/3806_DKpodcast_dwn3_tur/00eb5664-podcast-3806-306737.mp3' data-saveas='Ders 26 - Yalnızca birlikte olmak istiyoruz.mp3'>Ders 26 - Yalnızca birlikte olmak istiyoruz</a>
    <br />2: <a href='http://radio-download.dw.de/Events/podcasts/tur/3806_DKpodcast_dwn3_tur/00eb5675-podcast-3806-306736.mp3' data-saveas='Ders 25 - Önce ufak siparişler gelmesini umuyorum.mp3'>Ders 25 - Önce ufak siparişler gelmesini umuyorum</a>
..
...
....

</body>
</html>
Haydi sonucuna bakalım. Önce dosyanın indiğini chrome network sekmesinden görelim:
Şimdide tıkladığımızda ne olduğuna:
Hepsi bu :)

3 Ocak 2016 Pazar

Dipkazimi

İnsanın tarım yoluyla ürün elde etme çabası başladığından buyana insanoğlu, elde ettiklerini nitelik ve nicelik yönünden daha artırmak, ucuzlatmak ve kolaylaştırmak için çabalar harcamıştır. Tarımda alet- makinalı hizmetin başladığı 18. yy. dan günümüze kadar büyük ve hızlı bir gelişme olduğu görülmüştür. Günümüzde tarım, alet ve makinasız yapılamayacak bir düzeye ulaştırılmıştır.

Ülkeler, birim alandan en fazla verim alabilmek amacıyla tekniğin bütün imkanlarından faydalanmak için büyük çaba sarfetmektedirler. Ürün artışının faydalanmasında, uygun toprak işlemenin ve iyi bir tohum yatağı hazırlanmasının rolü büyüktür. Ancak bu şartları sağlamak için tarlaya sokulan her türlü toprak işleme aleti toprağın fiziksel yapısının bozulmasına neden olmakta ve bu aletlerin aynı derinlikleri işlemesi sonucunda da, toprak profilinin bu derinliğinde pulluk tabanı denilen sert bir tabaka oluşmaktadır. Bu sert tabakanın oluşmasına sadce sürüm aletleri neden olmamaktadır. Topraktaki bazı mineraller ve oluşumlar da sert tabakanın oluşmasına neden olmaktadır. Makinaların kullanılmasıyla sert tabakanın oluşmasında toprak nemi çok önemli bir faktördür. Ağır tavda yapılan sürümler bu tabakanın daha çabuk oluşmasına neden olmaktadır. Bu tabaka sert olduğu için toprağa giren suyu pulluk tabakasının altına geçirmez. Bitki köklerinin derinlere ulaşmasını önler. Bu yüzden bu tabakanın belirli aralıklarla kırılması, kabartılması gerekir. Bu amaç için de dipkazan aletleri kullanılır.

Toprakların traktörle işlenmesi sonucu oluşan sert tabaka, genellikle 20-25 cm. derinlikte bulunmakta, bu tabakanın kalınlığı da 6-18 cm arasında değişmektedir. Ağır bünyeli topraklarda sert tabaka toprak yüzeyinden daha derinde (yaklaşık olarak 35-40 cm) teşekkül eder. Ancak orta ve hafif bünyeli topraklarda sert tabaka oluşumu, ağır bünyeli topraklara oranla daha çabuk ve daha sert olmaktadır.

Sert tabaka oluşmasının zararları

Sert tabaka oluşması toprağın gözenekliliğini azaltır. Toprak sıkıştığından bitki köklerinin gelişmesi için ihtiyaç duyulan oksijen miktarı azalır. Kökler iyi gelişemez.

Sert tabaka toprağın geçirgenliğini azaltır. Yağmur, sulama suyu şeklinde toprağa giren sular sert tabakadan geçemez, bunun sonucu olarak toprak derinliğine işleyemez. Dolayısıyla toprakta yeterince su depolanamayacağından bitkiler kurak dönemlerde ihtiyaç duydukları suyu toprakta bulamayacaklar ve sonuçta verim düşüşü kaçınılmaz olacaktır.

Bitki kökleri sert tabakayı geçemeyecekleri için yukarı veya yana doğru kıvrılarak topraktaki bitki besin maddelerinden ve mevcut toprak suyundan yeterince yararlanamayacaklardır. Tüm bunların sonucunda verimde bitki çeşidine bağlı olarak %25- 30 oranında azalma olacaktır.

Sert tabaka hangi aletlerle kırılmalıdır?

Toprakta genellikle pulluk sürümü derinliğinde oluşan sert tabakanın kırılması, yani patlatılması gerekir. Bunun için en uygun zaman da toprağın hangi derinlikte oluştuğunu ve kalınlığının kaç santimetre olduğunu bilmeliyiz ki, ona uygun bir alet seçelim. Bunun için toprak incelenir. Yapılan çalışmanın sonucuna göre;

* Sert tabaka toprak yüzeyinden 20-25 cm. derinlikte oluşmuş ise çizel aleti kullanılır.

* Sert tabaka toprak yüzeyinden 30-40 cm. derinde oluşmuş ise subsoiler (dipkazan) aleti kullanılmmalıdır.

* Sert tabaka toprak yüzeyinden 65-70 cm derinlikte oluşmuş ise riper aleti kullanılmalıdır.

Sert tabakanın kırılmasının faydaları:

Sert tabakadan dolayı ıslaklık sorunu olan yerlerde sert tabaka kırılarak geç tava gelme durumu ortadan kalkar, erken veya zamanında ekim yapılması sağlanır. Toprağın havalanması ve toprağın su tutma kapasitesi artar. Toprağın derinlerinde bulunan besin maddelerinin alınması kolaylaşır.

Beklenen faydaların olabilmesi için;

* Sert tabakanın iyice parçalanması ile bunu sağlayacak çizel, dipkazan ve riper aletlerinin çekimi için en uygun zaman toprağın kuru olmasıdır. Bu nedenle sert tabakanın kırılması yaz aylarında yapılmalıdır.

*Sert tabakanın çok iyi parçalanması için çizel veya dipkazan aletinin yırtıcı kısımları (derinliği bakımından) sert tabakanın hemen altından geçirilmelidir.

* Sert tabakayı kırmak için kullanılan aletin çok sık veya çok seyrek aralıklarla çekilmesi beklenen faydayı sağlamaz. Aletin 90X90 cm. aralıklarla çekilmesi halinde sert tabaka iyice parçalanmakta ve rantabl olmaktadır.

* Sert tabakanın kırılmasında çizel ve dipkazan kullanılması halinde 4-5 yılda bir, riper kullanılması halinde ise 8-10 yılda bir kırma işlemi yeniden yapılmalıdır.