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

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 :)