yazılım,c# ve domates kabuğu

Product vs Platform şirketleri

  15/11/11 00:31, by ertan, Categories: Coding, Yazılım

Bundan bir süre önce Google+’ın başındaki kişi Steve Yegge aslında Google çalışanlarına gönderdiği bir makaleyi kazara public olarak yayınladı, biraz uzun olsa da herkese bu yazının içeriğini okumasını tavsiye ederim.

https://plus.google.com/112678702228711889851/posts/eVeouesvaVX

Henüz ülkemiz için erken olsa da (bu iyi bir şey), bu yazıdan öğrenilecek çok şey var. Bu yazıda beni en çok şaşırtan bir kamyon danışmanı olan bir şirket bunun nasıl farkına varmazdı ama neyse. Ben bizim şartlarımıza uyan başka bir konudan gitmek istiyorum.

Bizde de Google’ın yaptığına benzer gayet başarılı olmuş gayet çeşitli (bunun içerisine e-ticaret, ilan sitelerini, teknoloji şirketlerini de dahil ediyorum) ürünler var. Ancak bu şirketlerin başına Jeff Bezos gibi bir patron henüz gelmedi. Görünüşe göre de en az 1 jenerasyon boyunca da gelmeyecek.

Tüm bu bizim ürettiğimiz ürünlerin temel problemi bu Steve amcanın yazdıkları galiba. Başarılı bir ürün yarattıktan sonra onunla ne yapacağımızı bilmiyoruz.

Örnek isterseniz tüm başarılı olmuş, e-ticaret ya da ilan sitelerine bakın 1 tanesi bile elle tutulur bir API sağlamaz. Bu sitelerin patronları için bir kategorideki ürün listesi kaynak kodlar kadar değerli. Hatta web sitelerinden bu verileri almaya çalışırsanız size dava açarlar.

Bana göre asıl kaçırdıkları bu API’leri sağlayarak etraflarında yaratacakları ekosistem. Bir ürünü ayakta tutan aslında bu ekosistemdir. Microsoft bu ekosistemi daha ilk zamanlarından beri kullandı, bununla tüm karşısına dikilenleri yola getirdi. Facebook’da aynı yoldan geldi, şu anda canı sıkılan insanları eğlendirmesi için içinde yüzlerce uygulaması var.

Tersi örnek Google Maps. Eğer bu ekosistemi yaratacak API’leri sağlayamazsanız bir gün o ürünü sizden daha iyi yapan (misal Yandex Maps) gibi birileri mutlaka çıkar ve o gün aldatılırsınız. Başka bir örnek; sahibi bir kamu kuruluşu olmasına rağmen IBB Trafik sitesidir.

Halen ikna olmadıysanız; limitsiz kaynağınız olsa bile bu ekosistem’in yaratacağı inovasyon’a hiçbir zaman erişemezsiniz. Inovasyon olmadan sürekliliği sağlamanız imkansızdır.

Bu ekosistemi yaratmak için düşünülenin aksine ağır bir yükü omuzlamak gerekmiyor. Bezos’un kurallarını takip edin yeterli, eğer okumaya üşendiniz ya da anlamadıysanız ben özetleyeyim.

  1. Tüm takımlar (Bezos tam tarif edememiş, modül diyeyim) verilerini servisler ile yayınlayacak.
  2. Tüm takımlar arasındaki iletişim sadece bu servisler aracılığıyla olacak.
  3. Başka bir iletişim yöntemi geçerli değildir. Direk linkler, direk veri tabanı bağlantıları, arka kapılar yada benzeri hiçbir yöntem. Tüm iletişim bu servisler ile network üzerinden yapılacak.
  4. Ne tür bir teknoloji (HTTP, Corba, custom... ) kullandığınızın önemi yok.
  5. Tüm servisler dışarıya açılabilir olacak. Tüm bu servisler dış dünyadan geliştiricilere açılacak şekilde planlanıp, tasarlanacak.
  6. Bunları yapmayan kişi işten atılacak.

Bu maddeleri ben yazsaydım bu kadar güzel özetleyemezdim heralde :) Tüm tasarımınızı bu maddelere uyarak yaptığınızda gerisi kendiliğinden gelecektir.

Bunları yazmamın sebebi;

Eğer girişimciyseniz mevcut sitelere alternatif bir şeyler yapmak isteyip de mevcut olanlar yüzünden cesaret edemiyorsanız, bu konuda denemeye değer.

Eğer patronsanız bir an önce Bezos’un gönderdiği bir mail’in benzerini sizde gönderin çok geç kalmadan.

Eğer geliştiriciyseniz bir an önce proje, ürün, platform arasında ne fark vardır onu öğrenin.

Leave a comment »

Parallel kütüphanesi

  22/05/11 21:16, by ertan, Categories: Yazılım, Algoritma Soruları

Uzun bir aradan sonra sonunda hakkında yazabileceğim bir şey yeni aklıma geldi. Eğer yamulmuyorsam Parallel kütüphanesi Framework 4.0 ile beraber geldi, daha öncesinde MS Research'in geliştirdiği bir extension olarak gizli bir köşede saklanıyordu.

Parallel kütüphanesi ( yada AsParallel() ) Nedir ?

Parallel kütüphanesi son 2-3 yılda yeni çıkan birden fazla işlemcilerin avantajını kullanmak için işleri kolaylaştırmak amacıyla geliştirilmiş bir kütüphane.

Temel olarak yaptığı sıralı olarak yapılacak işleri birden fazla CPU'ya dağıtarak aynı anda birden fazla iş yapmaya, dolayısıyla da verilen işi daha hızlı yapar.

Neden ihtiyacım olur

Bundan yıllar öncesinde C yada ASM'de yazdığım zamanlarla karşılaştırınca, bisikletle bir ferrari'yi karşılaştırmaya benziyor. İronik olan kısım ise yazdığımız programlar halen o zamanki programlar kadar yavaş.

Önce herhangi bir programı yavaşlatan nedir diye düşünelim;

* Donanım

* Network

* For, Foreach, While gibi döngüler.

Bunların dışında bir programın yavaş çalışmasına neden olacak bir etken yok. Donanım ve Network kısmı için zaten sürekli olarak bir şeyler yapılıyor zaten konumuzun dışında.

Eğer yazdığımız kodun hızlı çalışmasını istiyorsak yapacağımız tek şey bu döngü'lere dikkat etmek, ne kadar az döngü varsa kod o kadar hızlı çalışacaktır. Bu optimizasyonu tabiki belli dereceye kadar yapabiliriz ve nihayetinde bazı kısımlar kalacak.

Standart kodlama yaparken (eğer thread filan yaratmıyorsanız) yazdığımız kod her zaman ve her zaman tek CPU üzerinde çalışacaktır. Bazen CPU bir şeylerle uğraşırken Task Manager'i açtığınızda tüm CPU'ların bir şey yaptığını görüyor olursunuz ancak burası biraz yanıltıcıdır.

Çok merak ediyorsanız basit bir loop yaratarak CPU'yu sürekli meşgul tutan bir kod çalıştırın ve Task Manager'da olanları izleyin, eğer 2 CPU'lu bir makinanız varsa test yaptığınız exe asla %50 (4 CPU'nuz varsa %25) cpu kullanımının üzerine çıkmayacaktır. Task Manager'ın grafik kısmına baktığınız zaman tüm CPU'larda aktivite gözükür ancak bu işletim sisteminin yapılan işleri farklı CPU'lara dağıtması yüzünden kaynaklanır. Yani kodunuz kısa bir süre 1. CPU daha sonra 2. CPU'da çalışmaya devam eder. Ancak yaptığınız iş tek CPU sınırını aşmadığı için asıl rakamlara baktığınız zaman bu söylediğim görünmez bariyer'de takılırsınız.

Yazdığınız kodu hızlandırmak için birden fazla CPU kullanmayı istiyorsanız kodunuz içinde ekstra olacak bir şeyler daha ekleyerek, niyetinizi belli etmeniz gerekir.

Nasıl ?

Anlaşılır olması için örnekli gidiyorum; basit bir örnek olsun diye elimizde bir int array'i olsun ve biz array üstündeki elemanı string halline dönüştürmek isteyelim. (Pratikde string'e dönüştürmekten başka bir şeyler olacaktır)

Önce array'i tanımlayıp içini çöp'le dolduralım.

Code

List<int> arr = new List<int>();
 
 
 
   for (int i = 1; i < 9999999; i++)
 
      arr.Add(i);

Standart olarak yazacağımız kod aşağıdaki gibi;

Code

a.ForEach(delegate(int i)
 
  {
 
      return i.ToString();
 
  });

Şimdi bu kodu benim 8 CPU'lu canavar bilgisayarımda çalıştırdığımda süre olarak 01.520 saniyede tamamlanıyor.

Aynı kod üzerinde biraz değişiklik yaparak paralel kütüphanesinin kullanılmasını istersem;

Code

arr.AsParallel().ForAll(delegate(int i)
 
  {
 
      string c = i.ToString();
 
  });

Araya eklediğim bu AsParallel ile çalışma süresi 0.619 saniyeye düştü.

Karşılaştırma yapınca arada devasa bir fark var. Geriye tek sorun kalıyor;

Paralel çalışacak kod parçası üzerinde sıralı işlemler yapmamanız gerekli, örneğin toplama gibi sıralı olması gerekmeyen bir kod yazabilirsiniz ancak bir önceki değere ihtiyacınız olduğu durumlarda işler biraz zorlaşabilir.

Böyle durumlar biraz daha karmaşık, bunun detaylarını daha sonra yazarım ancak sadece bu yöntemle kodunuz içindeki döngüler'in büyük bir çoğunluğunda bu parallel kütüphanesini halen kullanabilirsiniz.

Umarım işinize yaramıştır. Unutmadan denemek isteyenler için tüm test kodu aşağıda;

Code

List<int> arr = new List<int>();
 
 
 
for (int i = 1; i < 9999999; i++)
 
    arr.Add(i);
 
 
 
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
 
 
 
s.Start();
 
 
 
arr.ForEach(delegate(int i)
 
{
 
    string c = i.ToString();
 
});
 
 
 
s.Stop();
 
 
 
Console.WriteLine(" Sure : " + s.Elapsed);
 
 
 
s.Reset();
 
s.Start();
 
 
 
arr.AsParallel().ForAll(delegate(int i)
 
{
 
    string c = i.ToString();
 
});
 
 
 
s.Stop();
 
 
 
Console.WriteLine(" Sure : " + s.Elapsed);
Leave a comment »

turnaround time

  29/10/10 09:44, by ertan, Categories: Yazılım

Klavyem sanırım aşırı kullanım yüzünden o (noktalı olanı) harfini yazmamakta inat ediyor. çok uğraşamadım idare ediniz.

wikipedia'ya gore



Turnaround, in computing scheduling, the total time between submission of a process and its completion

anlamına gelen bu kelime biz farkında olmadan yazılım geliştirme için harcadığımız zamanın büyük bir bolumunu alır.

Diyelim ki ofisinizde sakin bir şekilde çalışırken, yazdığınız uygulamada ufak bir hata buldunuz. Basit anlamda bu süre IDE açıkken uygulamayı derleyip, hatayı deneyip, tekrar IDE'ye dondugunuze kadar geçen süredir aslında.

Çoğu developer bu süreyi etkileyecek sorunları çozmek yerine gozardı edip bir an once hatayı test etmeye odaklanır. Tanıdığım bir developer'ın yaptıklarını ornek vererek gideyim :)

1. Derle 45sn (7sn) Normalde çok kısa süren bu iş, diskinde yer olmadığı için kodları USB diskten kullanıyor bu yüzden çok yavaş.

2. Kopyala 90sn. (0sn) Normalde build script'i ile kopyalanan dll dosyası, build script'ini güncellemediği için elle kopyalamak zorunda. Derlenen dosyayı programı çalıştırdığı dizine kopyalıyor ama uygulamayı açık unuttuğu için dosyaları kopyalayamadı. programı kapatıp kopyalamayı tekrar başlatıyor.

3. Çalıştırma 35sn. (4sn) Her ne amaçla kullanıldığını anlamadığım bir cehennemden gelmiş bir antitrojan uyarı mesajı çıkarıyor. Mesaj kapatılıyor.

4. Deneme 70sn. (2sn) Denemek için uygulamadaki ekrana gidip parametreleri giriyor, ama hatayı oluşmadı. Biraz düşündükten sonra hatalı parametre girdiğini farkedip düzeltip tekrar deniyor. Hata düzelmemiş. tekrar baştan başla.

Bu saydıklarımın aslında daha fazlası var ama sıkıcı olmaması için daha detaylandırmadım. Şimdi normalde 13sn süren "turnaround" zamanı bu developer için 240 saniye yani 4dk.

Gün içinde bunu yüzlerce kez tekrar ettiğimiz için işimizi yaparken harcadığımız zamanın çok çok büyük bir bölümünü anlamsız, kimseye faydası olmayan, can sıkıcı işlerle geçiririz.

Verdiğim örnekler için bir build script'i ve unit test yapmanız yeterlidir ama yaptığınız işin detaylarını sizden başka kimse bilmez.

Bu konuda size sadece bazı genel olabilecek önerilerim olacak;

* Kod yazarken dikkatinizi dağıtacak, antivirüs, outlook gibi zıpır zıpır popup mesaj çıkaran şeyleri kapatın.

* Age of Empires eski makinalarda da çalışıyor olsa bile ofisdeki en hızlı makinayı kullanın, bunun için gerekirse patronunuza yalvarın. Şirketin bik bik standartları var bu yüzden veremeyiz denirse gidip kendinize hızlı bir makina alın, bu kendinize yaptığınız bir yatırımdır.

* Sürekli tekrar ettiğiniz şeyleri daha kısa sürede yapmanın bir yolunu bulun, gerekirse telefonda ağlayan kullanıcıyı beklemeye alıp browser'ın address barına günde 150 kere yanlış yazdığınız programın adresini bookmark'lara ekleyin.

* Yazdığınız uygulamayı arayüzler içinden test etmekten vazgeçin, felsefik saçmalıklardan olacak ama unit test için ilk adımı atmak uzun bir yolun ilk adımıdır.

* Geliştirdiğiniz uygulamayı güncellemek için tek tek dosya kopyalamaktan vazgeçin, hayır daha hızlı değil. Tüm değişmiş dosyaları güncelleyecek bir script dosyası yazın.

* Bunların içerisindeki en önemlisi "hurafe"lere inanmayın. 10dk önce çalışan bir şey mars'dan gelmiş kırmızı etekli uzaylılar tarafından bozulmuş olamaz.

Leave a comment »

asp.net ve web platformu ile ilgili tavsiyeler.

  20/10/10 20:27, by ertan, Categories: Yazılım

Bu aralar bende yeni bir projeye başladığım için geçmiş tecrübeleri bir köşeye yazmanın zamanı geldi diye düşünüyorum. Umarım bir gün faydasını görürsünüz.

Henüz hiç kod yazmadıysanız öncelikle geliştirdiğiniz uygulamayı kimlerin kullanacağı konusunda biraz düşünmeniz gerekiyor. Intranet (ofisiniz diyelim) içinde çalışacak bir uygulama ile internet üzerinden kullanılacak uygulama arasındaki uçurumların daha sonra farkına varabilirsiniz.

Bant Genişliği

Eğer intranet içerisinde ve sınırları aşmayacak kullanıcı adedinde olacak ise biraz daha rahat davranabilir bant genişliğini düşünmeden hızlı kod geliştirmeye odaklanabilirsiniz. Bu durumda ASP.NET kontrolleri yada MVC ile yol almakta fayda var. Bunlarla çok basit uygulamaları neredeyse hiç kod yazmadan arayüzlerle geliştirmeniz bile olası.

View State

Yeterli bant genişliği olsa bile IDE'den New Project dediğiniz anda web.config'den viewstate'i çok mecbur kalmadığınız sürece bir daha açmamak üzere kapatmanız iyi olacaktır.

Eğer kendiniz web controlleri geliştirecekseniz mecbur kaldığınızda control state'i kullanmaya çalışın. Yeniden hesaplayabildiğiniz şeyleri (DropDrown'ın listesi gibi) viewstate yerine veritabanı gibi ortamlardan oluşturun. Ancak hesaplayamadığınız (DropDown'ın seçili item'ı gibi) değerleri sadece control state'e yazın. Bu tercih ilerde sizi 60kb'lik html sayfasına karşılık 700kb'lik viewstate'den kurtaracak, hem network hemde cpu anlamında rahat etmenizi sağlar.

Login

Daha sonra uygulamanın kullanıcılarının sisteme nasıl giriş (login) yapacakları konusunda düşünmeniz gerekiyor.

Eğer tüm kullanıcıların AD (Active Directory) içerisinde hesabı var ise sizden şifre girilmeyen bir uygulama isteyeceklerdir. Bu yüzden Windows Authentication kullanmalısınız. Bu arada windows authentication sadece Internet Explorer ile çalışır, Firefox veya Chrome kullanmakta ısrar eden patronlarınız var ise şifre girmek zorunda kalacakları konusunda uyarmanız uyarmanız yerindedir.

Etrafta yeterince bilgi olduğu için Forms Authentication'ın detaylarına girmiyorum.

Uygulamanın giriş yapılmadan kullanılacak bölümleri (örneğin ana sayfa gibi) olacak ise giriş yapılacak bölümün dosyalarını ayrı bir dizin içerisinde tutun ve bu dizinde aşağıdaki gibi bir web.config dosyası tanımlayın. Böylece henüz login olmamış kullanıcılar bu dizin içerisindeki bir sayfaya erişmek istediğinde login sayfasına yönlendirilecektir.

XML

<configuration>
 
  <system.web>
 
    <authorization>
 
      <deny users="?"/>
 
    </authorization>
 
  </system.web>
 
</configuration>

Dil problemleri

Türkçe ve diğer tüm dil problemlerinden kurtulmak için web.config aşağıdaki şekilde olmalı;

Code

<globalization requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="utf-8" enableClientBasedCulture="true" culture="auto" uiCulture="auto" />

Şu anda hiç planınızda olmasa bile lokalizasyon için kullanılan resource dosyalarının kullanımını öğrenin.

Session

Eğer session içerisinde bir şey tutmamayı planlıyorsanız (-ki bu doğru yoldasınız demek) sessionState'i kapatarak biraz daha performans kazanabilirsiniz. Eğer aynı anda 100+ kullanıcıyı geçecek bir sistem geliştiriyorsanız, session kullanmanızı kesinlikle tavsiye etmem.

Hazır session hakkında konu açılmışken, eğer uygulamanız birden fazla sunucuda paralel olarak çalışacak (Load balanced yada Cluster diye geçer) ise mümkün olduğu kadar session kullanmaktan kaçının. Mecbur kalmanız durumunda session içerisine koyduğunuz nesnelerin serialize edilebilir olmasına dikkat edin.

Load balancing

Normalde session bilgileri web sunucusunun hafızasında saklanır. Yani siz sunucuyu kapattığınızda bu bilgiler kaybolur. Özel durumlar haricinde yük paylaşımı yapılan sunucularda session bilgileri sunucunun hafızası yerine serialize edilerek veritabanı üzerinde saklanır. Böylece 1. tıklamada A sunucusuna giden istek, 2. tıklamada B sunucusuna gittiğinde uygulama kaldığı yerden devam edebilir. Eğer bu konu size çok problem yaratıyor ise network sorumlunuz ile konuşarak bağlantı açan istemcinin hep aynı sunucu üzerinde kalmasını sağlayabilirsiniz. (Umarım karmaşık olmadı)

HTML

Boşluk karakterleri

HTML ile ilgili yapacağınız en iyi ve kısa optimizasyon ne kadar cici ve anlaşılabilir gelirse gelsin Visual Studio'nun aspx dosyaları üzerindeki salak indent'lerini kaldırmak olacaktır.

Nedeni ise çok fazla detay ve ascx tipi kontroller içeren sayfalar verilen indentler nedeniyle sunucunuzdan çıkacak olan " " (boşluk) karakterleri normal html boyutunu geçebilir.

Özellikle bu konuya liste tipi ekranlarda dikkat etmeniz gerekli. Örneğin listenin her satırında aşağıdaki gibi bir kodun tekrar ettiğini varsayalım.

Code

<asp:Panel runat="server">
 
      <asp:Button runat="server" Text="tıkla"/>
 
      <asp:Button runat="server" Text="hey"/>
 
    </asp:Panel>

Bu durumda browser'a 20 adet boşluk ve 4 tane yeni satır karakteri göndermiş oluyorsunuz. Toplamda bu 28 byte civarı bir şey yapar. Eğer listede 1000 adet kayıt listelenirse hiç kimsenin işine yaramayan 28kb'lik boş veri gönderiyor olursunuz. (Html boyutu dışında bunun sunucunuzda farklı etkileride var ama detayı sonra anlatırım)

Hyperlinkler

Bu bölüm çok önemli değil ama benim gibi titiz karakterli olanlar sevebilir.

Sayfalar içerisinde verdiğiniz linklerin anlaşılabilir olmasına aslında gerek yok. Örnekle gideyim;

bir arama kutunuz var diyelim;

Code

<form action="executesearch.aspx">
 
  <input type="textbox" name="aranacakkelime"/><input type="button" name="b"/>
 
</form>

Bu şekilde bir html yerine aşağıdaki gibi daha kısa kelimeleri seçebilirsiniz.

Code

<form action="es.aspx">
 
  <input type="textbox" name="k"/><input type="button" name="b"/>
 
</form>

Böylece sunucu ve browser arasında gidip gelen veri miktarını azaltabilirsiniz. Bu mantık arama kutusu için ben anlamlı gelmeyebilir ama örneğin arama sonuçları sayfasında verdiğiniz linklerde

Code

<a href="details.aspx?sayfano=5">Detay</a>

yerine;

Code

<a href="d.aspx?i=5">Detay</a>

hatta biraz biliyorsanız rewrite rule'lar ile;

Code

<a href="d/5">Detay</a>

verdiğinizde her satır için ilk örnekte 10, ikincide 19 byte kazanırsınız. Bu fazla gözükmeyebilir ama 1000 satır kayıt listelediğinizde 19kb kazanıyorsunuz demektir.

Resim linkleri

Bunu çok fazla kişi bilmez ancak neredeyse tüm browserlar gezinti yaparken sayfanın içeriğini sunucudan indirmek için site başına 2 ağ bağlantısı kullanır. Bu kullanıcı bir link'e tıkladığı zaman 1. kanaldan html içeriği indirilirken 2. kanaldan css,javascript,resim gibi diğer bilgiler indirilir. Örneğin 5 tane css dosyası kullanıyorsanız bu durumda neredeyse hepsi sıralı olarak sunucudan indirilir.

Bu tür bir problemi gidermek için farklı içerikleri aslında aynı siteyi gösteren ancak farklı isimlerle göstererek browser'ı kandırabilirsiniz. Yani css ve js dosyaları için farklı bir adres, resimler için farklı bir adres verebilirsiniz. Örneğin;

Code

<html>
 
<head>
 
  <link href="http://res.benimguzelsitem.com/css/elma.css" rel="stylesheet" type="text/css" />
 
  <link href="http://res.benimguzelsitem.com/css/armut.css" rel="stylesheet" type="text/css" />
 
</head>
 
<body>
 
  <img src="http://img.benimguzelsitem.com/img/jennajameson.jpg"/>
 
  <img src="http://img.benimguzelsitem.com/img/emilyscott.jpg"/>
 
</bod>
 
</html>

Şimdi bu yapıya göre "res.benimguzelsitem.com" ve "img.benimguzelsitem.com" web siteleri aslında "www.benimguzelsitem.com" ile aynı IP adresini kullanmakta (DNS tanımları üzerinden bunu yapabilirsiniz) ve hatta IIS üzerinde aynı dizini göstermekte.

Böylece browser'ı kandırarak normalde 2 yerine 6 kanaldan sayfa içeriğini indirmenizi sağlar, buda hızlı açılan sayfalar demek.

Şimdilik bu kadar.

Leave a comment »

Office 2010 elektronik imza yeniliği

  04/10/10 08:17, by ertan, Categories: Yazılım

Daha önce yazdığım gibi bir çok uygulama elektronik imza için basit olduğundan BES tipi imzaları atmayı yeterli görüyordu ama Office 2010 için (biraz şaşırsamda) bu konuda bir güzel değişiklik yapılmış.

Docx, xlsx gibi sonu x ile biten uzantılar ile dosya formatlarını daha önceden xml haline dönüştürmüşlerdi, (bilmeyenler için; docx uzantısını sadece zip şekline çevirin açılacaktır) şimdi de dokümanlara elektronik imza atılırken XaDES formatında atılmaya başlamış. Belki elektronik imza düşündüğünüz bazı projelerinizde işinize yarayabilir.

Leave a comment »

<< Previous :: Next >>

 

©2017 by Ertan Tike

Contact | Help | b2evo skin by Asevo | PHP framework | vps | François