19.07.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.
Nedir?
Web Deployment Tool basitçe web sitesnizi IIS üzerinde yüklemenizi, paketlemenizi ve yönetmenizi sağlayan IIS extension'ıdır. Visual Studio 2010'un one-click Publish özelliği ile entegre çalışabilir ve web uygulamalarınızı tek harekette uzak sunucuya gönderip yayınlanmasını sağlayabilirsiniz. Süper!
Kurulum bittikten sonra Windows Services'e (Services.msc) "msdepsvc" isminde eklenecektir. Çalışıp çalışmadığından emin olun yada "net start msdepsvc" komutunu bilgisayara verin.
Servis çalışmaya başladıktan sonra aşağıdaki adresi örnekleyerek erişebilrisiniz.
http://DOMAIN/MSDEPLOYAGENTSERVICE
örnek
http://178.18.193.88/MSDEPLOYAGENTSERVICE veya http://oguzhan.info/MSDEPLOYAGENTSERVICE
Size kullanıcı adı ve şifre soracatır. Deploy edeceğiniz web sitesinin IIS üzerinde belirtilmiş credantials'ını veya windows local userlarından sitenize erişim hakkı olan kullanıcı bilgisini girebilirsiniz.
VS.NET 2010'da Nasıl Oluyor?
View / Tool Bars / Web One Click Publish tool'unu aktif edin.
Yeni bir Publish profile oluşturun.
Publish method olarak "Web Deploy" seçin. (FPSE seçeneği ile göndermeyi denemyin yoksa FrontPage extensionları için bir kaç takla atmanız gerekiyor)
Service URL : http://DOMAIN/MSDEPLOYAGENTSERVICE gibi bir şey.
Site/Application : site ismini girmeniz yeterli veya IIS'te oluşturduğunuz Application ismi
Site için tanımladığınız Windows Local User veya IIS User olmadı Administrator hesabını girin.
Her şey yolundaysa direkt çalışır ve hızlıca web sitenizi IIS üzerine paketleyip gönderir.
15.07.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.
Projenin raporlama evrensini çok seviyorum, çünkü yazdığınız programın ne kadar işe yaradığını, neler yapabildiğini ve hatta neleri eksik yaptığını görebilmenizi sağlıyoru. Birde teknik işin çoğu drag&drop olduğu için biraz daha eğlenceli geliyor. Yine bir e-ticaret projesinin raporlama evresinde bir kaç sorunla karşılatık ve nasıl aştığımızı hatta bir tanesini aşamadığımızı paylaşmak istiyorum.
Report Builder 3.0'ın ve SQL Server 2008 R2'nin piyasaya çıkmasından doğal olarak gaza gelip raporlarımızı Reporting Services R2 üzerinden yayınlamaya ve oluşturmaya karar verdik.
Report Builder 3.0 çok kolay kullanılabilen ve hazırladığınız raporu direkt sunucuya göndermenizi sağlayan özelliklerle donatılmış. Raporlarınızı hemen oluşturup sunucuya gönderip servis üzerinden ister Web ister Windows Ugulamalarında kullanabiliyorsunuz. Müthiş rahatlık! ama bir kaç problem var.
Raporlarımızı oluşturup yayına hazır hale getirdikten sonra sıra kendi sistemimize implemente etmeye geldi .Net'in native kontrollerinden ReportViewer'ı kullanarak işe başladık. Karşımıza çıkan ilk sorun sunucudaki rapor'a ulaşırken Reporting Services'in kimlik doğrulama istemesiydi (Gerçi bunu kaldırabiliyorsunuz ama güvenlik nedeni ile pek yanaşmadık). ReportViewer kontorolünün içindeki "ServerReport.ReportServerCredentials" özelliğini kullanarak bu sorunu hallettik ama bunun için aşağıdaki kendi sınıfımızı hazırlamamız gerektir.
using System.Net; using System.Security.Principal; using Microsoft.Reporting.WebForms;
authCookie =null; user = password = authority =null;
returnfalse; }
public WindowsIdentity ImpersonationUser { get { returnnull; } }
public ICredentials NetworkCredentials { get { returnnew NetworkCredential(_username, _password, _domain); } } }
Aslında çok bir şey yok IReportServerCredentials Interface'ini implemente edip gerekli boşlukları doldurmanız yeterli. Bu class'ı kullanarak aşağıdaki şekilde ReportViewer'ın sunucudaki Repor'a erişmesini sağaladık.
ReportViewer1.ServerReport.ReportServerCredentials = new ReportServerCredentials("user","pass","domain");
Bu sayede kullanıcının herhangi bir şifre girmesine gerek kalmadan rapor'u görmesini sağlayabildik.
Akabinde karşımıza çıkan başka bir sorunda SQL Server 2008 R2 ile gelen Reporting Services'in raporları yayınlamak için kullandığı ReportViewer kontrolünün versionu oldu.
Reporting Services'in kullandığı kontrolün versionu 10.50.1600.1 fakat VS.NET 2010 ile gelen ReportViewer kontrolünün versionu 10.0.0.0'dı böyle olunca bazı yeniliklerden faydalanamıyorsunuz ve raportunuzdaki ileri, geri, arama ve yeni çıkan "Export to Data Feed" butonu çalşmıyordu biraz uğraşıp Reporting Services'deki kontrolleri local projemde çalıştırmayı denedim fakat fazla zamanımız olmadığından vaz geçtik ve bir sonraki refactoring'e bıraktık.
Burdan çıkabilecek ufak bir ipucu vermek gerekirse. Reporting Services'i çalıştığı dizin : C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer şeklindeydi. Şimdilik direkt sunucu üzerinden raporları çağırıyoruz. Sanırım VS.NET 2010'un SP1'i ile ReportViewer kontrolünün versionu 10.50.1600.1'e yükselir ve direkt projemize implemente edebiliriz.
Not: Report Builder 3.0 aracı sadece SQL Server R2 ile gelen Reporting Services ile entegre çalışabiliyor. Reporting Services'ın içinden çıkıyor setup'ı ama yinede burdan çekebilirsiniz.
22.06.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.
Iphone'u 4.0'a upgrade ederken önüme aşağıdaki döküman çıktı neler yeni diye merak edenler için paylaşayım dedim.
Üçüncü parti uygulamalar için çoklu görev desteği*
Uygulamalar arasında hızlı bir şekilde geçiş yapmak için çoklu görev kullanıcı arayüzü
Ses uygulamalarını arkaplanda çalma desteği
VoIP uygulamaları arkaplanda veya aygıt uyku durumundayken aramaları alabilir ve sürdürebilir
Uygulamalar konumu izleyebilir ve arkaplanda çalışırken işlem yapabilir
Uyarılar ve mesajlar, anında ilet bildirimleri ve yerel bildirimler kullanılarak uygulamalara anında iletilebilir
Uygulamalar görevleri arkaplanda tamamlayabilir
Uygulamaları daha iyi düzenlemek ve onlara erişmek için klasörler
Ana ekran duvar kağıdı*
Mail iyileştirmeleri
Tüm hesaplardaki e-postaları tek bir yerde görüntülemek için birleştirilmiş gelen kutusu
Farklı e-posta hesapları arasında hızlı bir şekilde geçiş yapmak için hızlı gelen kutusu değişimi
Aynı yazışmadaki birden fazla e-postayı görüntülemek için konularına göre gruplandırılmış iletiler
İlişikler, uyumlu üçüncü parti uygulamalarla açılabilir
Arama sonuçları artık dosyalanabilir veya silinebilir
Fotoğraf ilişiklerinin boyutunu seçme seçeneği
Giden Kutusu'ndaki iletiler düzenlenebilir veya silinebilir
iBooks ve iBookstore desteği (App Store'da bulunur)
Fotoğraf ve Kamera iyileştirmeleri
Fotoğraf çekerken 5x sayısal büyütme**
Video kaydı sırasında odaklamak için dokunma**
Yüzleri iPhoto'dan eşzamanlayarak aktarabilme
Coğrafi etiketli fotoğraflar, Fotoğraflar'daki bir haritada görünür
Aygıtta liste yaratabilme ve düzenleyebilme
Takvim davetleri, desteklenen CalDAV sunucularla kablosuz olarak gönderilebilir ve kabul edilebilir
MobileMe takvimi paylaşma desteği
Web'de arama sırasında öneriler ve son yapılan aramalar görünür
Aranabilir SMS/MMS mesajları**
Spotlight araması Web üzerinde ve Wikipedia'da sürdürülebilir
Geliştirilmiş konum gizliliği
Durum çubuğunda yeni Konum Servisleri simgesi
Son 24 saatte konumunuzu isteyen uygulamaların belirtimi
Konum Servisleri, uygulamalar için ayrı ayrı açılabilir veya kapatılabilir
Otomatik yazım denetimi
Bluetooth klavye desteği*
Uyumlu arabalardaki iPod arayüzü yoluyla müzikler, podcast'ler ve sesli kitaplar arasında dolaşmak için iPod çıkışı
Uygulamaları iTunes yoluyla hediye etme desteği
Notları, IMAP tabanlı posta hesaplarıyla kablosuz olarak eşzamanlama
Anında ilet bildirimlerini almak için sürekli WiFi bağlantısı*
Yalnızca hücresel veriyi açmak/kapatmak için yeni ayar**
Yeni SMS/MMS oluştururken karakter sayısını görüntüleme seçeneği**
Visual Voicemail mesajları sunucudan silinmiş olsa bile yerel olarak tutulabilir**
Düşey yöne kilitleme denetimi*
iPod ve üçüncü parti ses uygulamaları için ses çalma denetimleri*
Yeni diller, sözlükler ve klavyeler
Erişilebilirlik geliştirmeleri*
Bluetooth iyileştirmeleri
Aygıt parolasını şifreleme anahtarı olarak kullanarak daha iyi veri koruma* (Tam geri yükleme gerektirir.)
Üçüncü parti Mobil Aygıt Yönetimi çözümleri desteği
Kurumsal uygulamaların kablosuz olarak dağıtılmasını etkinleştirir
Exchange Server 2010 uyumluluğu
Birden fazla Exchange ActiveSync hesabı desteği
Juniper Junos Pulse ve Cisco AnyConnect SSL VPN uygulamaları desteği (App Store'da bulunur)
Geliştiriciler için 1500'den fazla yeni API
Hata düzeltmeleri
Bu yazılım güncellemeyle uyumlu ürünler:
iPhone 3G
iPhone 3GS
iPhone 4
iPod touch 2. nesil
iPod touch 3. nesil (2009 sonlarında çıkan 32 GB veya 64 GB modelleri)
* iPhone 3GS, iPhone 4 veya iPod touch 3. nesil gerektirir. ** iPhone 3G, iPhone 3GS veya iPhone 4 gerektirir. SMS/MMS mesajlaşmayı ve Visual Voicemail’i kablosuz iletişim operatörünüzün desteklemesi gerekir.
05.06.2010 tarihinde yazıldıktan sonra, 2 kişi yorum yazmış.
Daha önce bir çok kez uzaktan gözlem yaparak keşfettiğim ve teorik olarak bildiğim bir kavramın işleyişini gerçekten içinde yaşayarak deneyimledim.
Proje aslında ufak bir micro-site projesiydi (vargonenvds.com) burdan vargonen olarak virtual dedicated server satmaya karar verdik ve projelendirmeye başladık.
Projenin istediğimiz gibi işlemesi için gerekli olacak özellikler ne olmalıydı? Hangi özellikler olursa hem müşterinin hemde bizim ihtiyaçlarımızı en doğru ve hızlı şekilde karşılardı? gibi soruları Development Takımı (ben), ScrumMaster (Bu yine ben) ve Product Owner (Ali Vargonen) ile tartışıp cevaplarını bulmaya çalıştık.
Toplantı sonucunda önümüzde 28 maddelik bir liste vardı ve hepsini bitirmek 15 günümüzü alacaktı (karşımıza en başta düşünemediğimiz ve gerekli olacak bir sürü özellik daha çıkacak tabiki). Projeyi tasarlayıp kodlama aşamasına geçtikten sonra 28 maddelik base listemize bir 12 madde daha eklendi ve 40 madde oldu, ürün özelliklerimiz giderek artıyordu ve buna bir yerde dur demek gerekiyordu çünkü ürüne her yeni özellik eklendiğinde yayınlama tarihimizide ertelemek zorunda kalıyorduk ve böylece bir refleks olarak Release Backlog oluşturmaya karar verdik.
Ürünün istediğimiz işi yapabilmesi için minimum özellikleri belirledikten sonra diğer özelliklerin hepsini bir kerana attık, hatta üründe olmazsa olmaz "kredi kartı ile tahsilat" özelliğini bile release backlog'umuz içine almadık. En nihayetinde ürünümüzü minimum özelliklerle yayınlayıp duyuyrularını yaptık ve merakla siparişlerin gelmesini bekledik :)
Sonuç Olarak;
Ürün minimum özelliklerde umduğumuzdan daha iyi yorumlar ve geribildirimler aldı.
Yapılan geribildirimlerle front-end ve back-end 'de ki bug'ları kısa sürede belirleyip düzelttik.
Ürün "İndirim" ve "Kredi Kartı Tahsilat" özelliği olmadan 12 adet VDS siparişi aldık ve ücretlerini tahsil ettik.
Bu geçen zamanda, diğer önemli özellikleri ekledik.
Bu geçen zamanda bizim daha önce düşünemediğimiz ihtiyaçları gördük ve "Product Backlog"'umuza ekledik.
..Ve böylece bilinen bir gerçeği farkında olmadan tekrardan kanıtlayıp "haa demek bundan dolayı insanlar yazılım geliştirme süreçlerini oluşturmuşlar" gibi sözlerle saçmaladık.
fakat biz ilk belirlediğimiz özellikleri bitirip ürünü piyasaya 25 gün sonra çıkarsaydık ne sipariş alabilirdik, ne daha kararlı bir sistemimiz olurdu nede şimdi insanlar bu servisten yararlanıyor olurdu. Bu yazının konusunda daha karamsar ve isyankar olmuş olurdu.
02.05.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.
Her geçegün .Net Framework bataklığında daha da derinlere batıyoruz :) İhtiyaçlar gün geçtikce değişiyor ve buna bağlı olarak developer'ında program yazma şekli, ihtyaçları
değişiklik gösteriyor en son developer ihtiyaçlarına göre de .Net Framework değişiyor, gelişiyor. İşle bu arz-talep zincirinden çıkmış güzel bir tip daha Action Delegate.
Action .NET 3.0 ile birlikte developer'ın hayatına girmiş çok kullanışlı ve güclü bir delegate'tir. Genelde void tipindeki method'larla kullanılır ve geri dönüş değerini geriye döndürmez.
Ben genelde Collection nesnelerinde ForEach() methodunda kullanıyordum ama aşağıdaki gibi seksi yerlerde'de kullanma fırsatı buldum.
Action'ın ne olduğu zaten bir çok sitede yazıyor. Benim aktarmak istediğim nokta ise kullanım çeşitleri.
Hemen kod'a zıplayalım :
Örneğin bir hesap makinesı yapmaya kalkalım ve tasarlarkende Action delegate'ini kullanalım.
Bir hesap makinasında bir çok fonksiyon vardır. Kimi fonksiyonlar tek parametre alır, kimisi çift, kimisi belirsiz sayıda parametre alır yani Signature'ları farklıdır. Action burda yardımımıza koşuyor ve burdaki kod yönetim sıkıntısını aşmamızı sağlıyor.
class Islemler { publicvoid Topla(int X,int Y) { Console.WriteLine("Toplama İşlemi: {0}", X + Y); }
Hesapmakinesinin fonksiyonlarının tanımlı olduğu Islemler sınıfının method'larını Action delegate'imize tanımladık. Burda yine .NET 3.0 ile gelen Anonymous delegate'lerden faydalandık.
Örnek çok etkil olmadı ama en azından kullanımı ve ne işe yaradığı konusunda bilgi veriyor. Sonuçta farklı isimlerde ve farklı signature'da methodları tek bir delegate ile çalıştırabiliyoruz.
Action'a method tanımlamasını Lambda kullanarak aşağıdaki şekilde de yapabiliyoruz ve hatta yazının sonuna doğru biraz daha değişik syntax'ta Action tanımlaması yaptım.
Islemler islem =new Islemler();
Action action =()=> islem.Cikar(10,5); action();
Şimdi biraz daha seksi bir senaryo ele alalım.
Örneğin: Birçok method'unuzun içerisinde hep aynı pattern'i kullanacaksınız. Tüm methodlarınız farklı işler yapacak, farklı tipten ve farklı sayıda parametreler alıyor olacak.
Bu methodlarınız içinde hep aynı işlem kalıbını (pattern'ini veya rutini) kullanmanız gerektiğini varsayalım.
Bu methodların her birine ayrı ayrı belirlediğiniz pattern'i yazmak yerine Action delegate'ini kullanarak global bir method üzerinden pattern'i belirleyip methodlarımızı çağırabiliriz.
Yine işlemler sınıfımız üzerinden örnek vermek gerekirse :
class Islemler { publicvoid Topla(int X,int Y) { Console.WriteLine("Toplama İşlemi: {0}", X + Y); }
Islemler islem =new Islemler(); Exception ex =null; var action =new Action(()=> islem.Cikar(10,10));//Syntax'ı bu şekilde de olabiliyor ;) bool state = GlobalInvoker(action,out ex);
try { action(); ex =null; } catch(Exception e) { ex = e; cstate =false; }
return cstate; }
İşte gördüğünüz gibi GlobalInvoker methodunun içindeki tek bir desen ile tüm methodların düzgün çalışıp, çalışmadığını anladık ve hatta çalışmıyorsa debug için Exception'ımızı da sakladık.
Normalde Action delegate'ini kullanmasaydık tüm method'larımız bool değer döndürecekti ve hepsinde try-cacht blog'u kullanacaktık. Buda ek kod yazmamıza ve tabiki ek zamana mal olacaktı.
Birde bu class'ın 100 kadar method'u olduğunu düşünün!! Abov!
28.03.2010 tarihinde yazıldıktan sonra, 2 kişi yorum yazmış.
Power grubun yayınlarını yaptığımız için sık sık SHOUTcast,
Wowza ve Windows
Media Server gibi streaming yapan sunucularla muhatap
oluyoruz. Sunucular da ki ve radyolar da ki genel durumu görmek ve
bazı bilgileri toplamak için ufak çapta bir uygulama hazırlamaya karar verdik. Bizim için en önemli veri'de radyo'nun anlık dinleyici sayısıydı.
Wowza'nın
ve Windows Media'nin anlık user durumuna kolayca erişebildim fakat
SHOUTcast'in anlık kullanıcı durumuna erişmek o kadar da
kolay olmadı. Bu işi yaptıracak external bir tool yazmak içinde her
zamanki gibi zaman yoktu. Onun için SHOUTcast 'ın web sayfasına
bağlanıp basit bir HttpRequest
nesnesi ile işi halledebilirim diye düşündüm.
Fakat SHOUTcast
'ın Web server'ı belirli standartlara göre tasarlanmadığı için çeşitli
hatarlarla karşılatım
birinci kronik hata:
"The server committed a protocol violation.
Section=ResponseStatusLine"
Bu sorunun nedeni .Net
Framework'ün security anlayışı ile alakalıymış .Net 2.0'dan sonra useUnsafeHeaderParsing diye bir config ayarı koymuşlar. Bunla developer'ın bilerek saçma header'lar almasını
sağlamışlar. Aşağıdaki ayarı yaptıktan sonra bu hatayı atladım.
Stream oluşturup GetRequestStream() ile bellek'e
yerleştirdiğim zamanda Stream'in bilmediğim bazı şeyleri
desteklememesinden dolayı aşağıdaki hata ile karşılaştım.
"Cannot send a content-body with this
verb-type"
Daha sonra Request'i GetResponse()
ile HttpWebResponse'u alıp onunda GetResponseStream()
metodunu StreamReader'a alınca (burdaki Stream o bilmediğim bazı
şeyleri destekliyormuş sanırım). Bu sorunuda geçtik ve o güzelim
SHOUTcast HTML'sini parse etmek için string nesneme aldım.
Bankaların sanal pos hizmetleri sandığınız kadar stabil değil.
07.03.2010 tarihinde yazıldıktan sonra, 3 kişi yorum yazmış.
Goldmaster firması için yaptığımız bayi tahsilat sistemini nihayet bitirdik ve bayilerin kullanımına açtık. Her projede olduğu gibi bu porjede'de öngörülemeyen sorunlar hemen kendini gösterdi.
Bu sorunlardan en önemlisi sistemin bankalarla haberleşen modülü ile ilgiliydi. Sistemi kullanıma açtıktan sonra tahminimden fazla sanal pos transaction'ı gerçekleşmeye başladı ve sıklıkla "operation time-out" hataları ile karşılaşır oldum.
İşlemi debug edip simule ettiğimde ise bankanın sanal pos API'lerine erişim kurarken kullandığım HttpRequest sınıfının time out özelliğinin süresini 8 saniye verdiğimden kaynaklandığnı gördüm ve http isteğinin zaman aşım süresini 15 saniye olarak yeniden düzenledim ve publish ettim. Sonuç, "Operation Time-out" hataları gözle görülecek şekilde azaldı fakat yinede işlemlerin %5'i time-out'a düşüyordu. Durumdan sıkılıp sanal pos modülün muhatap olduğu tüm sanal pos Uri'lerini monitor etmeye başladım. Monitor'u şirket içinde kullandığımız PRTG programına devrettim. Bir kaçgün http üzerinden tüm web serverları geriye döndürdükleri cevap sürelerine göre izledim ve çok stabil olmayan bir tablo ile karşılaştım.
Bankaların sanal pos hizmeti verdikleri sunucuları gün içinde bir çok kez ya erişilemiyordu yada olağan dışı erişim süreleri ile hizmet vermeye çalışıyorlardı. Aksi daha detaylı incelemelerimde ise çok önemli bir sorunla karşılaştım. Şöyle ki;
Sanal Pos modülüm bankaya "parayı çek" emri gönderdikten sonra banka emri alıp işliyor fakat bana çok geç cevap verdiği için veya web sunucusunda ki anlık kesintilerden dolayı herhangi bir cevap dönemiyordu. Böyle olunca işlemi banka gerçekleştiriyor ve müşterinin kredi kartından para çekiyor fakat bizim sistemin haberi olmuyordu! arkasından sistem müşteriye para çekilemedi hatası döndürüyordu. Nedeni de "Operation time-out"!
Konu ile ilgili bir kaç banka ile görüştüm. Durumu açıkladığımda hepsi bana cross-check yapabilirsiniz dedi. Yani gün sonunda bendeki ve bankada ki kayıtları karşılaştırıp farklıları bulduktan sonra sisteme ekleyeceğim? Bunun işime yaramayacağını anlatım çünkü müşteriye işlemin sonucu kesin olarak işlem sonunda anlık bildirmem gerekiyordu. "Time-out exeption'ına düştüğümüzde kullanabileceğimiz bir validasyon yönteminiz var mı?" diye sorduğumda. Bu durum için geliştirdikleri bir tasarımlarının olmadıklarını söylediler.
Bana çok ilginç geldi... Böyle bir sorun varsa, bu kadar teknolojik bankaların bu sorunu bu zamana kadar çözebilmiş olduklarını düşünürdüm hep. Halbuki işlemin doğrulamasını farklı bir sunucudan yaptırabilirlerdi veya başka sunucu benim sunucuma bir http post geçebilirdi (Paypal bunu yapıyor) Bunun için sanal pos hizmetlerine ek ücret bile ekleyebilirlerdi ama hala bir çözüm üretemediklerine göre kredi kartı faizlerinden çok para kazandıklarından olsa gerek para saymaktan böyle şeyleri düşünecek vakitleri yok sanırım.
Sonuçta banka Uri'lerini izlemeyi 31 gün boyunca sürdürdüm ve sonuç olarak aşağıdaki gibi bir tablo çıktı karşıma.
Sanal Pos Uptime Süreleri
Tabloyu yorumlayacak olursak;
İlk üç bankanın downtime süreleri kabul edilebilir nitelikte olduğunu düşünüyorum. Bir saatin üzerindeki downtime oranları insanı biraz düşündürüyor. Fakat 8 saat ve üzeri kesinti ile hizmet veren bankalardan kesinlikle uzak durulması gerekiyor diye düşünüyorum.
Farklı bir yönden bakarsak olaya bankaların Uptime'ları (Sürekli Açık Kalma Durumları) %97'nin üzerinde. Doğru kulağa çok yüksek bir rakam geliyor ama %97.91 ile en berbat uptime süresine sahip Deniz Bank bile 31 günde 15 saat 58 dakika 15 saniye kapalı kalmış. Bu çok kabul edilebilir dir durum değil. Tabi bütün suçu bankaya yüklememek gerekiyor bağlı oldukları internet servis sağlayıcısının çeşitli ağ problemleride neden olmuş olabilir ama bunların hepsi günümüzde çözülmü olan problemler.
30 günlük izlemeye göre Türkiye'de en stabil ve hızlı sanal pos hizmetini Yapı Kredi bankası veriyor. Sana Pos API'lerininde kod tarafından yönetilebilir ve kolay entegre edilebilir olduğu düşüncesindeyim.
Yapı Kredi'nin 30 günlük http grafiği aşağıdaki gibi. En yüksek erişim süresi olarak 1.413ms görünüyor, en düşük 14ms. (Bu web server'ın client'a cevap verdiği süredir.)
Tabi en iyi bankayı söyledik. En berbat bankayıda söylemeden geçmeyelim. Deniz Bank'ın sanal pos hizmeti gerçekten berbat. Umarım bu durumu en kısa sürede düzeltirler ve insanlardan aldıkları paraların hakkını verirler.
Aşağıdaki grafikte'de görüldüğü gibi kapalı olmadığı zamanlarda web server'ın cevap verme süresi 7.445 milisaniye'ye kadar çıkmış en iyi cevap verme süresi ise 37 milisaniye, bu zaten diğer bankaların ortalama rakamı. :)
Ek olarak bankaların sanal pos hizmeti verdikleri web serverların kapalı olmadıkları zamanda cevap verme sürelerininde daha iyi olduğu düşünülebilir ama o kadarda iyi değil. Aşağıdaki grafik tüm bankaları grupladığından çok anlaşılır değil ama yinede istek ve yüzde olarak fikir verebilir.
Sonuç olarak bu 30 günlük verilere göre'de konuşmak doğru olmaz ama duruma şöyle bir anlık bakış attığımızı düşünürsek dikkat çekici bir husus. Daha farklı raporlar almakta mümkün ama benim ilgilendiklerim bunlardı. İlgilenen olursa XML veri dosyalarını gönderebilirim, zaman bazlı daha ayrıntılı raporlarda alınabilir.
14.01.2010 tarihinde yazıldıktan sonra, 5 kişi yorum yazmış.
Daha önce yazmış odluğum Logo API' ile ilgili yazıyı referans göstererek yazılmış bir çok e-posta alıyorum. Genelde e-posta içeriği SqlClause kullanımı ile alakalı olduğu için genel bir örnek yapıp burdan paylaşayım dedim.
Senaryomuz şöyle;
Logo üzerindeki bir carinin logo üzerindeki kodu ve ismini getiren bir sorgu yazmak istiyoruz. Bunun için de Logo api'sinde ki veritabanını bozmamak ve stabil, iyi sorgular oluşturmak için tasarlanmış SqlClause sorgu sınıfını kullanacağız. Bu sınıf'ı kullanarak yazdığınız sorgular kesinlikle logo'nun seveceği sorgular olup, sistem üzerinde herhangi bir probleme neden olmaz, kendileride zaten bu yöntemi öneriyorlar.
"Unity Object
kullanıcılara query yazmak için IQuery nesnesini sağlamıştır. IQuery nesnesi
ile Select tipindeki queryleri çalıştırmak hem çok kolay hemde çok hızlıdır.
Querylerle veri ilişkisini bozabileceğinden insert, update veya delete
tipindeki queryleri çalıştırma tavsiye edilmez, fakat IQuery nesnesi bu tür queryleri
çalıştırmanızada izin verecektir.
IQuery nesnesini kullanarak iki şekilde SQL cümleleri
oluşturabiliriz. İlk yöntem SQL cümlesini direct olarak Statement özelliğine
geçip OpenDirect veya Execute metodlarıyla çalıştırmak veya SQL Clause'lar
yardımıyla oluşturmak. Statement özelliğini kullanarak SQL cümlelerini
oluşturursak veri tabanına bağımlı hale geliriz. MS SQL Server için yazdığımız
bir sorgu ORACLE veya LBS UNITY programının desteklediği başka bir sunucuda
çalışmayabilir. Veri tabanına bağımlılığı ortadan kaldırmak için SQL Clause'lar
oluşturulmuştur. Clause'lar yardımıyla sorgumuzun belli kısımlarını tanımlar,
sorgunun birleştirilme kısmını UnityObject'e bırakırız. UnityObject
tanımlarımızı alır, UConfig programımızda belirtiğimiz veritabanı formatına
kendisi çevirir. Clauseları kullanmak biraz işyükü getirmekle beraber
veritabanı bağımlılığını ortadan kaldırır. Tanımladığınız sorgular LBS Unity
programının desteklediği ve ilerde destekleyebileceği ortamlara ek bir işlem
yapmanıza gerek kalmadan sorunsuz çevrilip çalıştırılacaktır"
Gelelim kod örneğine;
Ben .Net üzerinde C# kullanarak bir console uygulaması olarak geliştirdim.
class Program { static void Main(string[] args) { ARP_List(); }
static void ARP_List() { bool eof = false;
//COM bileşeni referansı oluşturuluyor UnityApplication unity = new UnityApplication(); if (unity.Connect()) { // Logo kullanıcısı ile giriş yapılıyor if (unity.UserLogin("LOGO_KULLANICISI", "SIFRE")) { // Hangi firma üzerinde işlem yapılacağı "firma no" ile belirleniyor. if (unity.CompanyLogin(310)) { //Yeni bir sql sorgusu çalıştırmak istediğimizi belirtiyoruz. Query qr = unity.NewQuery();
// Gerekli olan alanları (field) SelectClause ile belirtiyoruz. qr.SQLClause.SelectClause.New("A.CODE", "code"); qr.SQLClause.SelectClause.New("A.DEFINITION_", "def");
// Hangi tablo ile veri işleyeceğimizi belirtiyoruz. qr.SQLClause.FromClause.NewTable("LG_310_CLCARD", "A");
// Sorgumuzun kriterlerini belirtiyoruz. // Burda CODE'u 100'e eşit olan firmalar listeleniyor. qr.SQLClause.WhereClause.New("A.CODE", RelationalOperator.roEqual, "100", LogicalOperator.loNone);
//SQLClause ile oluşturulan sorgunun çıktısı Statement özelliğine atanıyor. qr.Statement = qr.SQLClause.SQL;
// Sorguyu çalıştırıyoruz. if (qr.OpenDirect()) { eof = qr.First(); //İlk kayıt isteniyor. Yoksa false döner;
//First(); ile alınan ilk kayıt bilgisi okunuyor. while (eof) { Console.WriteLine("{0}\t{1}", qr.QueryFields[0].Value, qr.QueryFields[1].Value);
eof = qr.Next(); // Sonraki kayıt isteniyor. Yoksa false döner; } }
11.01.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.
Yazılım
geliştirirken bizi sırtlayan programlama çatısının özelliklerini tek
tek ve çok ayrıntılı bilmemiz her zaman mümkün olmuyor, fakat bazı
özellikler var ki hem geliştirilen programın kalitesini, hem de
performansını büyük ölçüde etkileyebiliyor. Bu etkiyi C# programlama
dilinde yaratabilecek özelliklerden bir tanesi de Struct (Yapı) veri
tipidir ve konuda budur.
Bilindiği gibi Struct ile yapılabilen
her işlemi ve daha fazlasını Class ilede yapılabiliyor. Peki neden
Struct kullanalım? diye sorabilirsiniz. Aşağıda bu sorunun cevabını
kendi tecrübelerime dayanarak vermeye çalıştım.
Struct
bir değer türü olduğu için oluşturulduğunda Stack bellek bölgesinde
tutulur. Stack bellek bölgesinde yeni bir nesne tanımlamak ve nesneye
erişmek, class'ların tutulduğu Heap bölgesinden daha hızlıdır.
Programın
struct nesnesi ile işi bittiğinde Garbage Collector anında devreye
girip lazım olmayan struct nesnelerini temizler. Böylece siz programcı
olarak bu kaynağı işi bitti diye tekrar serbest bırakmak zorunda
kalmazsınız.
Algoritmanızda Birden fazla değişkeniniz varsa
bunları tek tek yönetmek yerine Struct ile bu değişkenleri tek bir
veritipi haline getirebilirsiniz.
Ben OOP'nin tüm
nimetlerinden yararlanmak istiyorum ama struct kadar performanslı da
olsun diyorsanız yine struct içinde method, constructor, değişken ve
indexleyici kullanabilrisiniz.
Struct, aynı class gibi private, public, internal, protected, protected internal değerlerini alabilir.
Struct'lar İçiçe tanımlanabilir (Nested Structure) hemde çok zevkli olur.
Tabi
Struct'ı her zaman kullanacağız diye bir şey yok, sadece işimize
geldiği zaman kullanalım. Bazı durumlarda da aşağıdaki nedenlerden
dolayı hiç kullanmamalıyız.
Struct'lar bir birlerinden türeyemez (Inheritance) ama birden fazla Interface'den türeyebilir.
Struct'lar
da yapıcı (Constructor) method varsayılan olarak parametresizdir ama
yinede siz kendi parametrik yapıcı metodlarınızı tanımlamayabilirsiniz.
Herhalükarda varsayılan yapıcı metod çalışacaktır.
Programınız içinde nesneler arası bağlantı, kompleks ilişkiler varsa struct kullanmamalısınız.
Struct'lar da statik üye tanımlayabilirsiniz ama nesneyi yarattıktan sonra erişemezsiniz.
Struct'lar
neredeyse her yönü ile Class'lara benzerler yalnız class'lardan biraz
daha kısıtlıdır ama daha da hızlıdır. Yukarıdaki maddeler size nerede
struct kullanmanız gerektiği hakkında az çok fikir verebilir ama doğru
karar vermeniz için tecrübeniz olması gerekir çünkü bu meslekte tecrübe
herşeydir ;)
Class ve Struct'ı basitçe karşılaştırıp aradaki
farkı performans açısından ele almak için basit bir test programı
hazırladım bakalım sonuç nasıl çıkacak.?
class Program { class clsHayvanlar { public string a { get; set; } }
struct srtHayvanlar { public string a { get; set; } }
List cls_list = new List(); for (int i = 0; i < 1000000; i++) { cls_list.Add(new clsHayvanlar() { a = "value" });// Heap bellek bölgesinde yer ayrılıyor. tmp_ = cls_list[i].a; // Heap bölgesinden okunuyor. } s1.Stop();
List str_list = new List(); for (int i = 0; i < 1000000; i++) { str_list.Add(new srtHayvanlar() { a = "value" }); // Stack bellek bölgesinde yer ayrılıyor. tmp_ = str_list[i].a; // Stack bölgesinden okunuyor. } s2.Stop();
----------------- class : 232,00 ms struct : 90,00 ms
Görüldüğü gibi Struct lehine bariz fark var ama bu durumun tam tersi olduğu zamanlarda olabiliyor tabi bu ayrı bir yazı konusu.
Ben
genelde Struct'ı dağınık verileri toparlamak, çoğu zamanda yeni bir
veri türü oluşturmak için kullanıyorum, gerisi zaten GC'a ve
Framework'e kalıyor. Genelde kullandığım yapı aşağıdaki gibi. Yeni bir
veri türüne ihtiyacım varsa bu türü yaratırken Struct kullanmam işimi
fazlasıyla görüyor.
class Program { static List d_list; static void Main(string[] args) { d_list = new List(Directory.GetFiles(".\\").Length);
foreach (var item in Directory.GetFiles(".\\")) { d_list.Add(new sistem_dosyasi( new FileInfo(item))); } }
struct sistem_dosyasi { public long size; public string name;
02.01.2010 tarihinde yazıldıktan sonra, 3 kişi yorum yazmış.
Yine opensource bir uygulamanın kodlarını incelerken bazı yerleri refactor ettiğimde daha hızlı çalıştığını gördüm. Revize ettiğim yerlerde genelde operator'lerin kullanımı ile alakalıydı. Böyle bir kaç gereksiz ve performans düşürücü kod ile karşılaşınca da operatör performans'ı ile ilgli birşeyler yazmaya kadar verdim ;)
Sık sık kullandığım ve kullanmaya dikkat ettiğim karar verici operatörlerin kullanım yerleri ve karşılaştırmalarını basit olarak gösteren giriş seviyesi bir yazı oldu.
C# Condition'lar
Condition'dan kastımız if, switch, :?, ?? gibi operatörlerin yerine göre kullanı mı, karar verme mekanizmalarınızın hızlı
olmasını sağlayacaktır. Örnek vermek gerekirse aşağıdaki gibi string
karşılaştırması yapacaksanız switch kullanmanız en performanslı sonucu
almanızı sağlayacaktır.
static void switchCondition(string hayvan) { switch (hayvan) { case "At": break; case "Öküz": break; case "Eşşek": break; case "Kedi": break; case "Köpek": break; case "Ejderha": break; default: break; } }
Bu
kodun aynısını if blok'u ile de yapmanız mümkün fakat her ne olursa
olsun switch bu durumda çok daha hızlı çalışacaktır. Gel gelelim
switch'inde kötü performans verdiği yerler var. Aşağıdaki if kullanımı
da switch'den daha performanslı çalışacaktır.
static bool IfOrCondition(string hayvan) {
return (hayvan == "At" || hayvan == "Öküz" || hayvan == "Eşşek" ||
hayvan == "Kedi" || hayvan == "Köpek" || hayvan == "Ejderha");
}
Bu kodun birde switch karşılığını elealırsak aşağıdaki gibi yapı çıkıyor. Burda da if daha hızlı karar veriyor.
static bool switchOrCondition(string hayvan) { switch (hayvan) { case "At": case "Öküz": case "Eşşek": case "Kedi": case "Köpek": case "Ejderha": return true; default: return false; } }
Bire
bir değer karşılatırırken de == (Eşittir) operatörü yerine Equals
metodunu kullanmanız performansınızı hızlandıracak bir harekettir. Bunu
ufak bir test programı yazarak karşılaştırdım ve aşağıdaki gibi bir
sonuç çıktı.
static void EqualsCondition(string hayvan) { if (hayvan.Equals("At")) {
} else if (hayvan.Equals("Öküz")) {
} else if (hayvan.Equals("Eşşek")) {
} else if (hayvan.Equals("Kedi")) {
} else if (hayvan.Equals("Köpek")) {
} else if (hayvan.Equals("Ejderha")) {
} }
== : 9,7233 ms Equals : 0,8875 ms
Özellikle string karşılaştırırken Equals kullanmanız performans açısından yararınıza olacaktır.
Bazı
durumlarda da ne if, nede switch kullanmanız gerekmez, Diğer dillerde
olduğu gibi C#'da da Inline kullanılabilecek operatörler vardır ve
gerektiğinde kullanılırsa hem kodunuz daha kolay okunur hemde
performans kazanırsınız. If kullanarak uzun uzun oluşturduğunuz bu kod bloğunu.
Bu iki kod arasındaki karşılaştırma sonucunda da aşağıdaki gibi bir sonuç çıktı.
If : 0,9262ms :? : 0,4659ms
Inline
kullanabileceğimiz diğer bir operatörde ?? operatörü'dür. Herhangi bir
nesnenin null olup olmadığını kontrol eder eğer null ise
belirleyeceğiniz değeri nesnenin değerine atar. Bu operatörü yine if
ile karşılşatırırsak aşağıdaki gibi bir If kullanımını.