16 Mart 2012 Cuma

[Cin Fikir - Mini Trick] DoIf(...)

Selamlar dostlar;
C# 3.0'ın bize verdiği Lambda Expression nimetine ne kadar şükretsek az :) Bugün sizinle işimi kolaylaştırdığını düşündüğüm küçük bir kod bloğunu paylaşacağım.
Aşağıdaki gibi if blokları sıklıkla karşılaşırız. Çoğunlukla okuması zordur. Üstelik, nesnenin 2 defa üretilmesine neden olduğumuz için de performansdan da yeriz..

if(this.GetType().GetProperty(setSecurityPair.Key).GetSetMethod() != null)
{
 this.GetType().GetProperty(setSecurityPair.Key).SetValue(this,null,null);
}


Burada bir reflection kod bloğu görmekteyiz. ve "this.GetType().GetProperty(setSecurityPair.Key)" kısmının da tekrar etmekte.. Peki kod bloğunu aşağıdaki hale dönüştürsek ?
this.GetType().GetProperty(setSecurityPair.Key).
       DoIf(me => me.GetSetMethod() != null, me=> me.SetValue(this,null,null));

Nasıl? Güzel olmaz mı :) DoIf(...) methodumuz, birinci lambda delegate'i çalıştırıyor; true değeri dönmesi durumunda da ikinci delegate çalıştırıyor. İki delegate de parametre olarak nesnenin kendisini alıyor; böylece de nesnenin tekrar üretilmesinden de kurtulunmuş oluyor.. Pekiiii.... Nasıl mı implemente ediyoruz?
public static class CodeHelpers
{
       public static void DoIf<T>(
                               this T instance, 
                               Func<T,bool> ensure, 
                               params Action<T>[] actionList) where T : class
       {
           if (ensure(instance))
           {
               foreach (var action in actionList)
               {
                   action.Invoke(instance as T);
               }
           }
       }
}
  • Satır 4: Bu bir extension method
  • Satır 5: İçine T tipinde değişken alan, geriye bool dönen bir method delegate
  • Satır 6: İçine T tipinde değişken alan bir method delegate
Çok basit bir yöntemle daha okunabilir ve kısa bir kod bloğu ortaya çıkartmış olduk..

Umarım sizin işinize de yarar, vizyonunuza "Cin Fikir"ler katar :)

28 Mart 2011 Pazartesi

[Yazılım Felsefesi] Asp.Net'de MVVM'i Denemek

Merhaba Arkadaşlar;

Bu makalenin kaynak kodlarını CodePlex'deki Adresinden (AspNetMVVM_TryOut.rar) indirebilirsiniz.

Bu yazı fikirsel çalışmalarımı yayınladığım "[Yazılım Fesefesi] UI Pattern'ler ve MVVM Üzerine Fikirsel Çalışmalar" makalemin uygulama örneğidir.

Önceki yazıda fikirler ortaya atmıştık. Sonra hayal ettim, bir şeyler ortaya çıkarttım. Sizinle paylaşmak istedim.
Asp.Net üzerinde MVVM denemeleri yapmaktaki öncelikli amacım; Code-Behind kodlamadan kurtulmaya ve UI Bussiness'ı bir tür model'e almaya çalışmaktı. Bunu kısmen gerçeklediğimi söyleyebilirim. Peki bu söylediğim şeyi Asp.Net MVC yapmıyor mu? Evet bir kısmını yapıyor. Controller sınıfları, bir tür Façade olarak Bussiness Logic'i View'dan kurtarıyor. Peki yeterli geliyor mu bu? Hayır. Çünkü sayfalarımız çoğu zaman UI tarafında da bir tür bussiness taşıyor. Biz bunu Asp.Net MVC'de javascript ile hallediyoruz. Asp.Net'de ise (iğrenç)Postback mimarisi ile hallediyoruz.Tamam sevmiyorum Postback mimarisini ama yine de işimizi oldukça kolaylaştırıyor. Çoğu intranet tabanlı Web uygulaması da -büyük dezavantajlarına rağmen- Asp.Net'i tercih ediyor.
Ben de Asp.Net'i tercih ettim :)
Tabii ki Asp.Net'i MVVM'e uygun hale getirebilmek için biraz üzerinde çalıştım. Mesela Asp.Net sayfasından Model oluşturabilmek için Custom Control ve bu kontrollerden veri toplayan bir Custom DataBinding mekanizması kullandım. Aslında şu anki haliyle çook basit bir durumda bu proje ama hayal ettiklerimi gerçekleyebilmemi sağladı.
Yeterince geyik yaptım :D Artık koda geçelim..
Mimarimizin ana amacı UI Bussiness'ı ViewModel'e taşımak olunca, basit bir UI Bussiness örneği bulmamız gerekiyordu. Ben de en sık karşılaştığımız (bir o kadar da karmaşık :D) Cascading Dropdown örneği üzerinden gerçekledim. Kaskat olarak birbirine bağlı 3 ComboBox'dan İl-İlçe-Semt seçimini gerçekleyeceğiz. Modelimiz sadece bu 3 kontrolün CanSet property'lerini düzenleyerek, View üzerinde işlem yapmaları sağlanacak. O zaman ViewModel'imize bakalım.
Bu arada mimarinin henüz önemli bir kısmı eksik.. O da Model ve ViewModel tek sınıfta. .Ama mantığı taşıması açısından kodun yeterli olduğunu düşünüyorum ;)

public class AddressViewModel : ViewModelBase<AddressViewModel>
{
    //Default olarak ViewModel'in property'leri Get ve Set edilebilir mi (CanGet)
    protected override bool DefaultAccess { get { return true; } }
    
    //Model üzerindeki propertyler
    public int? IlID { get; set; }
    public int? IlceID { get; set; }
    public int? SemtID { get; set; }

    protected AddressService addressDataService = new AddressService();

    //UI Logic ya da UI Bussiness
    protected override void PrepareBussiness()
    {
        this.CreateAccessRule("IlceID", AllowFor.Get | AllowFor.Set, () => this.IlID.HasValue);
        this.CreateAccessRule("SemtID", AllowFor.Get | AllowFor.Set, () => this.IlceID.HasValue);

        this.AddDatasource("IlID", () => this.addressDataService.IlData());
        this.AddDatasource("IlceID", () => this.addressDataService.IlceData(this.IlID.Value));
        this.AddDatasource("SemtID", () => this.addressDataService.SemtData(this.IlID.Value, this.IlceID.Value));
    }
}
Bizim için buradaki önemli kısım "PrepareBussiness" methodu.. Dikkat ederseniz CreateAccessRule ile IlceID, IlID'nin değeri olup olmadığına bağlanıyor. Hakeza SemtID'de IlceID'ye bağlanıyor. Burada dikkat etmemiz gereken bir nokta var. Default ayarda biz Model'imizi erişime açmış olmamıza rağmen, aşağıda Get ve Set property'lerini bir üst değerin var olmasına bağlıyoruz. Yani IlID'nin bir değeri olmadan IlceID Get(Visible) ve Set(Enabled) edilemez.. Meali: İl seçilmeden Ilce görüntülenmeyecek..

Bir diğer önemli nokta da erişimi denetleyen kısımların de birer delegate(Func<bool>) olmaları.. Böylece her erişim denendiğinde; belirtilen Rule çalıştırılacak ve sonuç dönecektir.Tabii ki bu Rule'lar ViewModelBase<> sınıfında Dictionary<string,Func<bool>> içinde tutuluyor.
Peki Model'in property'leri sayfaya nasıl yerleşecekler?
<p>
    İl:
    <bss:MyDropDownList ID="ddlIl" runat="server" BindColumnName="IlID" DataTextField="Title" DataValueField="ID">
    </bss:MyDropDownList>

</p>
<p>
            İlçe:
    <bss:MyDropDownList ID="ddlIlce" runat="server" BindColumnName="IlceID" DataTextField="Title" DataValueField="ID">
    </bss:MyDropDownList>
</p>
 <p>
            Semt:
    <bss:MyDropDownList ID="ddlSemt" runat="server" BindColumnName="SemtID"  DataTextField="Title" DataValueField="ID">
    </bss:MyDropDownList>
</p>

Burada kontrolü sınıfın ilgili kontorlüne Bind edebilmek için kendi Custom Controllerimizi kullanıyoruz. Önemli nokta BindColumnName niteliği.. Bu özellik sayesinde, rekürsif bir metod ile Page ile Model'i bind edeceğiz.
Şimdi.. İşin kalbine gelelim.. Code-Behind'a..
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ViewModelHelper.Run<AddressViewModel>(this);
    }
}
Sizi gülümsetebildiğimi umuyorum :) Hayallerimizi azar azar gerçekliyoruz. Peki ne mi var ViewModelHelper sınıfında ?
public static void Run<TViewModel>(Control mainControl) where TViewModel : ViewModelBase<TViewModel>, new()
{
    TViewModel viewModel = DataBindHelper.GetModel<TViewModel>(mainControl);
    viewModel.RunBussiness();
    DataBindHelper.ConfigureView(mainControl, viewModel);
}
Sistemi ayağa kaldıran kısım burada yatıyor.
  • 3. satır: Rekürsif bir method tüm kontrolleri dolaşıp IMyControl'den türeyen kontrollerin verilerini topluyor ve verilen Model'in BindColumnName'lerinde belirtilen property'lerine basıyor.
  • 4. satır: ViewModel sınfımızda yazdığımız RunBussiness() kısmını aktive ediyoruz.
  • 5. satır: ViewModel sınıfında oluşan rule'lar çerçevesinde, View'ı konfigure eder. (Verilerini Bind Eder, CanGet ve CanSet'ler çerçevesinde Visible ve Enabled'ları ayarlar. Varsa Datasource'larını bind eder.)
3. ve 5. satırdaki methodlar birbirine benzer olduğu, sadece ters çalıştıkları için sadece bir ConfigureView methodunu göstereceğim. Elbetteki kaynak kodlardan tüm diğer ayrıntılara ulaşabilirsiniz.
public static void ConfigureView<TViewModel>(Control mainControl, ViewModelBase<TViewModel> viewModel) where TViewModel : ViewModelBase<TViewModel>, new()
{
    Type dataType = viewModel.GetType();
    var properties = dataType.GetProperties();
    foreach (Control ctrl in mainControl.Controls)
    {
        if (ctrl is IMyControl)
        {
            IMyControl myControl = (ctrl as IMyControl);
            if (string.IsNullOrEmpty(myControl.BindColumnName)) continue;

            PropertyInfo propInfo = properties.
                    Where(pi => pi.Name == myControl.BindColumnName).
                            First();

            object dataValue = propInfo.GetValue(viewModel, null);

            myControl.setValue(dataValue);

            myControl.Visible = viewModel.CanGet(myControl.BindColumnName);
            myControl.ControlEnabled = propInfo.GetSetMethod() != null && viewModel.CanSet(myControl.BindColumnName);

            if (myControl is DataBoundControl && viewModel.HasDataSourceFor(myControl.BindColumnName) && myControl.ControlEnabled)
            {
                (myControl as DataBoundControl).DataSource = viewModel.GetDatasourceFor(myControl.BindColumnName);
                (myControl as DropDownList).AutoPostBack = true;
                (myControl as DataBoundControl).DataBind();
            }
        }
        if (ctrl.Controls.Count > 0)
        {
            ConfigureView(ctrl, viewModel);
        }
    }
}

Buradaki önemli nokta baştan beri söylediğimiz CanGet, CanSet methodlarının burada kullanılmış olması.. ViewModelBase sınıfından Datasource atama ile ilgili diğer methodların da burada işlevsel hale geldiğini görmekteyiz.
Ve son olarak da ViewModelBase sınıfımızdan küçük bir kaç nüans gösterelim :)
public abstract class ViewModelBase<TViewModel> where TViewModel : class,new()
{
..........
   private Dictionary<string, Func<bool>> getSecurityTable { get; set; }
   private Dictionary<string, Func<bool>> setSecurityTable { get; set; }

   internal bool CanGet(string propertyName) { return getSecurityTable.ContainsKey(propertyName) ? getSecurityTable[propertyName]() : DefaultAccess; }
   internal bool CanSet(string propertyName) { return setSecurityTable.ContainsKey(propertyName) ? setSecurityTable[propertyName]() : DefaultAccess; }
..........
   protected void CreateAccessRule(string propertyName, AllowFor allowment, Func<bool> allowMethod)
   {
       if ((allowment & Component.AllowFor.Get) > 0)
       {
           if (getSecurityTable.ContainsKey(propertyName))
           {
               getSecurityTable[propertyName] = allowMethod;
           }
           else
           {
               getSecurityTable.Add(propertyName, allowMethod);
           }
       }
       if ((allowment & Component.AllowFor.Set) > 0)
       {
           if (setSecurityTable.ContainsKey(propertyName))
           {
               setSecurityTable[propertyName] = allowMethod;
           }
           else
           {
               setSecurityTable.Add(propertyName, allowMethod);
           }
       }
   }
..........
}
Burada da AccessRule'ları Dictionary'lere atmamızı ve, CanGet ile CanSet canlı kanlı halleriyle ne kadar küçük birer method olduğunu görmenize yetti sanırım :) Nesneye Dayalı Programlama'ya bu yüzden bayılıyorum. İşlerimizi bu kadar kolay hale getiriyor :D Artık sizi kaynak kodlarla başbaşa bırakıyorum..
Umarım [Yazılım Felsefesi]ne bakışınızı değiştirebilecek, genişletebilecek bir makale olmuştur..
Herkese iyi çalışmalar dilerim..

18 Mart 2011 Cuma

[Yazılım Felsefesi] UI Pattern'ler ve MVVM Üzerine Fikirsel Çalışmalar

Merhaba Arkadaşlar;

[Yazılım Felsefesi] başlıklı makalelerle, sizlerle hayallerimi paylaşacağım.. Sorun olarak alıglayıp; çözüm için zihnimi zorladığım fikirler üzerine fikirler ortaya atacağım..

Uzun zamandır düşündüğüm ama tam olarak çözüm üretemediğim sorun vardı:

Çok katmanlı Mimari'ye uygun olarak tasarlanan Bussiness katmanı -ya da -; sisteme dair Bussiness Logic kodlarını barındırıyor. Ancak UI Logic(ya da Application Logic) olarak ifade edebileceğimiz kodları hiç bir şekilde arayüz bağımsız hale getiremiyorduk.  Daha fazla detaya girmeden hemen kısaca bu kavramları açıklayalım:

  • Bussiness Logic: "Bir e-ticaret portalında satışın onaylanması için girilen Kredi Kartının, sipariş boyutunca provizyon vermiş olması gerekir." gibi sistemsel kural ve mantığa denir.
  • UI Logic(App Logic): "Adres girme ekranında İl combosu seçildiğinde, İlçesi combosu İl'de seçilen değere göre doldurulur." gibi ön arayüzü ya da kısaca Bussiness Katmanından önce bir model'in kullanıcı tarafından manüple edilmesi olaylarına bu ad verilir. "Hesaplar listesinde, 10.000 TL'den büyük aylık geliri olanların kırmızı görünmesi" gibi kural örnekleri de verilebilir.

Asp.Net MVC bu trendin başlancını bence çok güzel verdi. Model üzerine;

  • Validation
  • Control Type(Ön arayüzdeki gösterilecek kontrolün şekli (EditorFor(...) ya da DisplayFor(...) gibi))
  • FormatString
  • DisplayName(Alanın Kullanıcıya gösterilecek ismi)

gibi alanlar yerleştirerek UI'a bu bilgilerin konulmasının önüne geçmeye çalıştı.. Aslında Model üzerine konulabilecek bence önemli bir kısım daha var..

Model Based Security diye sallama bir tabir yaptım bu fikir için :) Amacım aslında Model'lerimize, nesne bazlı ya da property bazlı security ayarları koymak(bu Controller'ların üzerine Authorize(Role="Admin") gibi olabilir). Örnek vermek gerekirse;

  • ForumPost nesnesinin sadece CreateUser tarafından değiştirilebilmesi, 
  • Kisi modelinin Ad, Soyad bilgilerini CreateUser değiştirebilmekteyken, Maaş bilgisini sadece Admin değiştirebilmesi
  • Kisi modelinin tüm kayıtlarını Maaş hariç görebiliyor, kendi maaşını görebiliyor vb.

Her şeyin nesneye dayalı olması için bu da güzel bir teknik ama hala bazı isteklerimizi karşılamıyor. UI Logic için bir çözüm bulmalıyız.. Peki MVVM'e ne dersiniz?

Model-View-ViewModel tabiri bize biraz daha başlancıç oluşturuyor. ViewModel kelimesini de; Model of View'a çevirdiğimizde daha da anlaşılır. İlk aklıma gelen şey, "İl" combosuna bir dropdown gibi erişebilmemizi sağlayacak bir sınıf.. Aslında bu sınıf; ..aspx.cs sınıflarımız oluyor.. Bizim için korkutucu, sadece daha fazla karmaşıklığa neden olan sınıflar.. O zaman biraz daha farklı bir bakış açısından gitmeliyim..

Model'den sayfaya.. Test Driven yazarken; sayfayı hayal edip; kodsal olarak test etmek..

Sayfa üzerinde en sık kullandığımız Applicaiton Logic: Visible ve Enabled.. Peki Model üzerinde nasıl tasarlayabiliriz bunu ?

  • CanGet : Visibility
  • CanSet : Enabled
  • CanInvoke : Button Enabled

olarak ifade etsek model üzerinde ? Ortaya aşağıdaki gibi pseude-code çıksa?

 

model.Ensure(c=> c.Il.HasValue).AllowForSet(c=> c.Ilce);


 



Bu bize aslında testlerimizi de ortada bir UI yokken bile yapabilmemizi sağlamaz mı mesela:



 



public int IlceID{
get
{
if ( ! this.CanGet("IlceID"))
thow new Exception();
return _ilceId;
}
set
{
if ( ! this.CanSet("IlceID"))
thow new Exception();
return _ilceId;
}
}


 



gibi bir kodu rahatlıkla test edebiliriz.



 



public void TestWeCanNotSetIlceBeforeSetIl()
{
AdresModel adres= new AdresModel();
Assert.ThrowsException(()=>adres.IlceId=5);
}

public void TestWeCanSetIlceAfterSetIl()
{
AdresModel adres= new AdresModel();
adres.IlID=3;
Assert.DontThrowException(()=>adres.IlceId=5);
}


 



Tabii ki property'ler sürekli tekrar eden böyle bir koddan Proxy sınıflar aracılığıyla kurtarır ve temiz bir kod elde etmeye çalışırız. Zaten ChangeTracking amacıyla çoğu zaman model'lerimiz proxy nesneler halinde erişmekteyiz - ki bunu da bize ORM'lerimiz sağlar...



Peki bunu nasıl uygulayabilirim. Bir de bunu üzerine beyin jimnastiği yapalım:



 



Asp.Net MVC'de Model'lerin bind edilme mimarisi hazır zaten. Yaptığım ek değişiklikleri de Html.DisplayFor(...) mimarisi ile gerçekleyebilirim. Ancak Controller ile ViewModel'i birbirinden ayırmam çok zor olacak.



Asp.Net WebForms daha stateful olduğu için belki işime yarayabilir. Asp.Net'in kendi kontollerinden inherit alarak kendi Custom Contol'lerimi yazarsam bunları da Model'in property'lerine bind edecek bir sistem geliştirirsem güzel olabilir.



 



Bu fikri sevdim :) Şimdiden heyecanlanmaya başladım :)



Bakalım hayal ettiklerimi ne kadar gerçekleyebileceğimTongue out

16 Mart 2011 Çarşamba

[Tekerleği Yeniden Keşfet] Katılgan ORM

Merhaba Arkadaşlar;

Bu makalenin kaynak kodlarını CodePlex'deki Adresinden (KatılganORM.rar) indirebilirsiniz.

 

ORM(Object Relational Mapper) kelimesini duyunca "Yeni bir ORM mi?" diye sorduğunuzu duyuyor gibiyim Smile Zaten bu yüzden başlığımız [Tekerleği Yeniden Keşfet]..

"Tekerlek bir kez keşfedilmişken, niye yeniden emek vereyim ki?" diye düşünmeyin. İnsanlık 1969'da Amerika'lı astronotların Aya çıkmasının 40 yıl sonrasından bile; Çin uzaya insan göndermeye çalışıyordu. Burada amaç aynı zorlu süreçten geçip; benzer hataları yapıp, ders alıp tecrübe edinmek... Bizde burada kendi küçücük "Katılgan ORM"mizi yaparken aynı şekilde tecrübe etmeye çalışacağız.

Tabii ki çok ihtiyacımız olmadıkça NHibernate'den ya da Entity Framework'den vazgeçmeyeceğiz.. Ama ihtiyacımız olunca da kullanmaktan kaçınmayacağız (Maalesef bir projemde benim ihtiyacım oldu. Laughing)

Amacımız oldukça basit bir ORM çıkartmaya çalışmak. Özellikleri aşağıdaki gibi olacak.

  1. Select All, Select By Example gibi basit işlevleri olacak.
  2. Update,Insert, Delete işlemleri olacak..
  3. Gelen Relational bir kaydı Nesne olarak dönecek(Sanırım Object kelimesi buradan geliyordu :)
  4. Ek olarak Basit bir BaseService aracılığıyla direk DB'ye sorgu atmamıza izin verecek, istersek bir sınıfa map edecek..

Kodumuzu olabilidiğince küçük tutumak için DB bağımsızlığını tam olarak implemente etmeyeceğiz. Bu da size ödev olsun :)

Her şeyden önce DB ve Entity'mizi görelim.

public class Kisi
{
[PrimaryKey(IsIdentity = true)]
public int KisiID { get; set; }
public string Ad { get; set; }
public string Soyad { get; set; }
public string TelNo { get; set; }
}




Gördüğünüz gibi, entity sınıfımız olabildiğince basit.. PrimaryKey Attribute'u var o da yine çok basit bir sınıf.



İlk adım Program.cs üzerinde yeni bir kişi nesnesi oluşturup DB'ye göndermek, ardından da edindiği ID değerini ekrana yazdırmak.



 



DataContext<Kisi> kisiContext = new DataContext<Kisi>();
Kisi yeniKisi = new Kisi { Ad = "Tahir", Soyad = "çakmak", TelNo = "9876543" };
kisiContext.InsertEntity(yeniKisi);

Console.WriteLine("Eklenen Kisi'nin ID'si: {0}", yeniKisi.KisiID);


 



DataContext<T> sınıfımız ORM'imizin tek anlamlı, kod barındıran sınıfı.. Üzerinde bütün işlemlerimiz için birer anlamlı method barındırıyor. Tip Güvenlilik için Generic olarak tasarladık.



 



public class DataContext<TEntity> where TEntity : class, new()
{
........
public TE RunCommand<TE>(Func<DbCommand, TE> dbExecute, string conStr)
{
DbConnection con = this.CreateConnection();
DbCommand cmd = con.CreateCommand();
try
{
con.Open();
return dbExecute(cmd);
}
catch (Exception e)
{
throw new Exception("DB Hatası", e);
}
finally
{
con.Close();
}
}
........
}


 



DataContext sınıfımızın en temel methodu "RunCommand" methodu; bu bize bütün DB isteklerinin tek bir noktadan akmasını sağlıyor. Dikkat ederseniz, bu method bir "Template Method Pattern"inin C# 3.0 implementasyonu.. İçerisine DBCommand'ı parametre olarak alıp, dışarıya veri dönen tüm methodlar için işlem noktası.. Diğer noktalarda, Con'ın açılıp-kapanması, ya da hata'ların yakalanması ile ilgili merkezi nokta..



 



public bool InsertEntity(TEntity entity)
{
return RunCommand(cmd =>
{
object identityValue = GetInsertQry(entity, cmd).ExecuteScalar();
var propInfo = entity.GetType().GetProperties().Where(pInfo => pInfo.GetCustomAttributes(typeof(PrimaryKeyAttribute), false).Length > 0).FirstOrDefault();
if (propInfo != null && (propInfo.GetValue(entity, null) == null || ((int)propInfo.GetValue(entity, null)) == 0))
{
propInfo.SetValue(entity, Convert.ChangeType(identityValue, Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType), null);
}
return true;
});
}

public DbCommand GetInsertQry(TEntity entity, DbCommand cmd)
{
if (entity is BaseEntity) { (entity as BaseEntity).IsSaving = true; }

string columns = "";
string parameters = "";
foreach (PropertyInfo info in typeof(TEntity).GetProperties().
Where(p => p.GetSetMethod() != null
&& p.GetCustomAttributes(typeof(NonDbColumnAttribute), false).Count() <= 0
&& (p.GetCustomAttributes(typeof(PrimaryKeyAttribute), false) as PrimaryKeyAttribute[]).ToList().Where(pr => pr.IsIdentity).Count() <= 0
)
)
{
object columnValue = info.GetValue(entity, null);
if (columnValue != null)
{
columns += string.Format("{0},", info.Name);
parameters += string.Format(" @{0} ,", info.Name);
cmd.Parameters.Add(this.CreateParameter(info.Name, columnValue));
}
}

StringBuilder querySb = new StringBuilder();
querySb.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})", typeof(TEntity).Name, columns.Remove(columns.LastIndexOf(","), 1), parameters.Remove(parameters.LastIndexOf(","), 1));

cmd.CommandText = querySb.ToString() + "; SELECT SCOPE_IDENTITY();";

return cmd;
}


 



GetInsertQuery methodu adı üsütünde :) InsertQuery'sini Parametreleriyle beraber oluşturup geriye DBCommand döndürüyor.



Burada yaptığı şey aslında çok basit; reflection ile gelen entity'nin tüm değerlerini alıyor, tek tek kolon ismiyle birebir olarak Insert cümleciğine yerleştiriyor; parametre olarak da değerini veriyor. Property'leri dolaşırken önemli bir nokta var. Metodumuz; PrimaryKey ve Identity olan property'leri, NonDbColumnAttribute attribute'una sahip property'leri, ve de Set özelliği olmayan  property'leri DB'ye göndermiyor..  



Peki gelen kayıtları nasıl nesneye dönüştüreceğiz, reflection ve Convert.ChangeType(...) methodu ile Laughing



 



public List<TEntity> GetAllData(string orderByColumn = "", params string[] columnNames)
{
return RunCommand(cmd =>
{
cmd.CommandText = GetSelectQry(columnNames) + (orderByColumn == "" ? "" : " ORDER BY " + orderByColumn);
return MapEntity(cmd.ExecuteReader());
});
}

public string GetSelectQry(params string[] columnNames)
{
StringBuilder sb = new StringBuilder();
sb.Append("Select ");
if (columnNames.Length > 0)
{
for (int i = 0; i < columnNames.Length; i++)
{
sb.Append(columnNames[i]);
if (i != columnNames.Length - 1) { sb.Append(","); }
}
}
else { sb.Append(" * "); }

sb.AppendFormat(" From {0}", typeof(TEntity).Name);
return sb.ToString();
}


 



Yukardıdaki kısımlar, Insert bölümünden farksız.. Yine string işleme.. Ve sistemin kalbi.. Mapping kod bloğu



 



public List<TEntity> MapEntity(IDataReader dr, params string[] exceptColumns)
{
List<TEntity> entityList = new List<TEntity>();
while (dr.Read())
{
TEntity entity = new TEntity();
var props = typeof(TEntity).GetProperties();
foreach (PropertyInfo info in props)
{
foreach (DataRow row in dr.GetSchemaTable().Rows)
{
if (row[0].ToString().ToLowerInvariant() == info.Name.ToLowerInvariant())
{
info.SetValue(entity, FormatHelper.AssignValue(dr[info.Name], Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType, !exceptColumns.Contains(info.Name)), null);
}
}
}
entityList.Add(entity);
}
return entityList;


Burada bize en çok yol gösteren IDataReader üzerindeki GetSchemaTable() methodu. Veritabanından gelen kolonların tiplerini belirtiyor; böylece gerekliyse bizim dönüşümleri sağlamamıza yardımcı oluyor.. Bir diğer durum da Nullable alanların gerçek tiplerini almamızı sağlayan Nullable.GetUnderlyingType metodu..



Kaynak kodları karıştırıyorken, BaseService<T> sınıfıyla karşılaşacaksınız. Bu sınıf DBContext<T> sınfını kullanan; Data Access Facade amacıyla kullanılan Servis katmanı için bir üst sınıfdır.



Sistem genel olarak Select, Update ve Delete için aynı işlemleri tekrar etmek üzerine gidiyor.. Ancak buraya kadar ki kısmın bir sonraki bölümleri incelemkte yeterli olduğunu düşünüyorum. Ve Sizleri kaynak kodlarla başbaşa bırakıyorum Laughing

[Rehber Makale] Distributed Transaction

Merhaba Arkadaşlar;

[Rehber Makale]'ler ile sizlere özel bir konu hakkında bilgi tekrarı olmadan, sizlere pratik tecrübelerimi aktardığım makaleler ulaştırmayı planlıyorum.

Nedir bu Distributed Transaction?

Bir uygulamada oluşan kayıtların birden fazla ve/veya birbirinden farklı markalardaki kayıtların tek bir transaction içerisinde işlem görmesidir. Bizim burada inceleyeceğimiz kısım; WCF üzerindeki uygulamalarıdır.

 

Başlangıç için okunması gereken makaleler:

1. WCF - Transaction Yonetimi (Transaction Management) – 1

2. WCF - Transaction Yonetimi (Transaction Management) – 2

3. 6 steps to enable transactions in WCF

Bu makaleler başlangıç için oldukça iyi fikir verecektir.

Önemli olan sadece bir kaç nokta vardır: WCF Binding Transaction ayarı; 1-2 attribute

Distributed Transaction Coordinator (MSDTC.exe)

Microsoft tarafında distributed transaction görevini üstlenen araçtır. Default olarak Windows sistemlerde kurulu bir servistir... Servislerde yukarıdaki isimlerle görüntüleyebilirsiniz. Com üzerinden iletişime geçilir. (Ki .Net ‘de arka planda Com üzerinden iletişime geçmektedir.) Yapı hakkında net bilgiler veremiyor olsam da şunu söyleyebilirim. WCF üzerinden bir Distributed Transaction(DT) isteğinde bulunduğunuzda(ki TransactionScope bunun için yeterlidir) MSDTC Database dahil tüm transaction işlemlerini kendisi yönetir. Sql Server ve Oracle kendi servisleri aracılığıyla; DTC için API’lar sağlamışlardır. (Oracle için Oracle Client’ın custom kurulumunda görebileceğiniz OracleMTSRecoveryService- MTS(Microsoft Transaction Server)) servisi ile gerçekleşir.

Oracle’ın işi tam olarak nasıl yürüttüğü ile ilgili Oracle® Services for Microsoft Transaction Server Developer's Guide adlı güzel bir kitabı var. Bu kitapta gördüğüm ve DTC’ye ait tek şema aşağıdaki resim bir çok konuda bilgi sahibi etmekte bizleri:

image

 

Sorun çözmek üzerine

MSDTC’nin en kötü yanlarından bir tanesi de sorunun ne olduğunu anlamanın zorluğu... MSDTC’nin çalışmasını gördüğümüz 2 yer var:

1- Component Services(Control Panel’a Administrative Tools) üzerinden

a. Computer - My Computer – Distributed Transaction C.. - Local DTC – Transaction Statistics bölümün de erişiebilirsiniz.

b. Tüm transactionları görebilmek için Local DTC’nin sağ tuş Properties – Trace sekmesinde “Trace All Transactions”ı seçmelisiniz.

c. Statistics ekranındaki verileri sıfırlamak için servisi restart etmeniz gerekli

2- Daha ayrıntılı bilgi için C:\Windows\System32\Msdtc\Trace altında bir log dosyası oluşturuyor.Bu dosyayı okumak için şu makaleyi kullanabilirsiniz. Kısa ayrıntılar aşağıda:

a. Tracemft dosyası için Windows XP Service pack 2 Support Tools’u adresinden indirebilirsiniz. WinRar gibi bir araçla açıp Tracefmt.exe ve traceprt.dll dosyalarını yukarıdaki belirtilen dosya yoluna atın.

b. Eski logları arşivlemek için Component Services’da Local DTC Prop’da Logging Options bölümünde Stop Session – New Session diyebilirsiniz. Eski loglar bir dosyaya atılır.

c. Yaptığınız işleme ait güncel logu dosyadan okuyabilmek için Local DTC’den ‘Flush’ diyerek buffer’dakilerin yazılmasını sağlayabilirsiniz.

d. msdtcvtr –tracelog dtctrace.log –o aa diyerek çalıştırabilir ve logları inceleyebilirsiniz.

3- Sql Server’da çalışıyorsanız; SQL Profiler’da trace etmek için Event’lar arasından (TransactionsàDTC Transactions)’ı seçerseniz DTC transaciton çağrılarını inceleyebilirsiniz.

C# tarafında yazdığınız kodlar üzerinde ise aşağıdaki yöntemleri kullanarak sorunu algılamaya çalışabilirsiniz.

1- Aldığınız hatanın Inner Exception’ında Com hata (hexadecimal)kodunu şuraya sorabilirsiniz.

2- TransactionScope içerisinde o anki transaction’a yakalamak için “Transaction.Current” demeniz yeterlidir.(System.Transactions.dll’i refere etmeniz gerekebilir.)

a. Altındaki TransactionInformation Distributed ID dahil olmak üzere yeterli bilgi vermektedir.

b. Transaction Status’une buradan bakabilirsiniz.

Önemli Not: Debug işlemi uzun sürerse Transaction TimeOut’a düşer.

 

Bilinen Hatalar

Aynı TransactionScope içerisinde hem başka bir WCF servisi çağrılır hemde DB’ye(OracleConnection ile) bağlanılmaya çalışılırsa; connection transaction commit edilmeden kapatılmaması gerekiyor. Aşağıdaki kod örneği bunu açıklıyor:

Bu hatayı temel olarak şu şekilde yakaladım:

1- Transaction.Current.TransactionInformation altındaki Status property’sine Watch ekledim. Kısa bir takip sonucu sorun; ortaya çıktı.

ImyServiceClient myClient = new ImyServiceClient();

using (TransactionScope TranScope = new TransactionScope(TransactionScopeOption.Required))
{
try
{
myClient.AddRecord();
Connection = new OracleConnection(ConnectionString);
Command = new OracleCommand(Query);
Connection.Open();
Command.ExecuteNonQuery();
//Yanlış yerde
//Connection.Close();
TranScope.Complete();
//Doğru yer.
Connection.Close();

}

catch (Exception)
{
TranScope.Dispose();
throw;
}
}


İp Ucu : Servis üzerinden çağrımlarda; Connection.Close() edilme komutu verilmiş olsa dahi; transaction’dan haber bekliyor. Ancak aynı yerde hem yeni bir servis çağrımı hem de direk connection açılması gerekiyorsa yukarıdaki gibi bir sorun ortaya çıkıyor.



İp Ucu: Transaction bittiğinde işlem yapmak istiyorsak; Transaction.Current.TransactionCompleted eventına register olmamız yeterli..

28 Ocak 2011 Cuma

Cin Fikir: No Client WCF !

Merhaba Arkadaşlar;

Bugünden itibaren, "Cin Fikir" diye ifade ettiğim; kodlamaktan da oldukça hoşlandığım bir kaç sıradışı fikrimi sizlerle paylaşmaya karar verdim. Cin Fikir'lerim genelde bir sorun görüp, bunu nasıl bir "Cin"lik ile çözebilirim ana fikrinden ortaya çıkan fikirler oluyor. Bugünkü fikrimiz WCF ile ilgili:

Problemin Tanımı: Outsource olarak bulunduğum bir iş yerinde, her şeyin olabildiğince servislere yıkılmasını ve gerektiğinde de farklı server ya da uygulamalara geçirilmesi; "Yazılım Geliştirme Stratejisi" olarak belirlenmişti. Ancak bu durum; küçük bir veri çekme işleminde dahi yazılan servislere bir client oluşturulması zorunluluğu getiriyordu. Üstelik de servis sayısı arttıkça; development için kullandığınız PC her servis çağrısı için TCP portlarına veri göndermek zorunda kalıyordu ve performansı çok düşük oluyordu. Üstelik geliştirilen uygulama gerçek ortama alınıp da servisler aynı PC'ye kurulursa, gereksiz olarak performans kaybına uğranıyordu.

Cin Fikir ! : Servis çağrılarını bir Façade sınıf üzerinden, interface üzerinden çekersek; concrete sınıfı da bir konfigurasyona göre ürettirirsek Bussiness kodlarını DLL üzerinden ya da WCF üzerinden çağırmamızı  bilmeden kod yazabiliriz. Bir de bu interface'i Servis sınıfına implemente ettirip, Client sınıfını da bu inteface'i implenmente edecek bir proxy nesnesiyle oluşturursak deymeyin keyfimize :D Daha fazla beklemeden kodlamaya geçelim...

Kodlama:
İlk olarak Service Interface'imize ve implemetasyonuna göz atalım.
[ServiceContract]
public interface IComplexService
{
    [OperationContract]
    int Sum(int x, int y);
}

public class ComplexService : IComplexService
{
    public int Sum(int x, int y)
    {
        return x + y;
    }
}
Karşınızda çok komplex bir servis :)
Şimdi de methodu çağıran sınıftaki kod'a göz atalım. Bu bir Console uygulaması..


class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(
           Core.ComplexService.Sum(2, 5)
        );
        Console.ReadLine();
    }
}
Burası sistemin can alıcı noktalarından birisi; Core sınıfı üzerindeki ComplexService static property'si IComplexService tipindedir. Bu property içinde Configuration içinden aldığımız değere göre gerçek nesneyi ya da WCF üzerinden çağrıyı gerçekleştirecek proxy sınıfını geri döndürüyoruz.

public static class Core
{
    public static IComplexService ComplexService
    {
        get
        {
            if (ConfigurationManager.AppSettings["userService"] == "1")
                return new ComplexService();

            return new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService")
                               .CreateChannel();
        }
    }
}
Burada belirtilen ChannelFactory sınıfı; Visual Studio'nun WCF Client kod üreticisinin ürettiği koda benzer şekilde verilen konfigurasyona ve service interface'ine göre, verilen interface tipinde WCF client nesnesi üretmekte.. Yani bir tür proxy nesnesi.. Buradaki sıkıntımız, bizim WCF method çağrımlarında her method'dan önce ve sonra işlem yapmak zorunda olduğumuzu varsaydığımızda sıkıntı çıkartması..

Bu durumda kendi proxy nesnelerimiz üretebileceğimiz bir yapıya ihtiyaçımız var. Bunun için bir çok çözüm var; biz burada RealProxy nesnesini kullanıyor olacağız. (Konu hakkında ayrıntılı bilgi için Sefer Algan Hocam'ın yazdığı CSharpNedir'deki şu makalesine göz atabilirsiniz).


internal class ProxyFactory<TObject> : RealProxy
{
    public TObject RealObject { get; private set; }

    public ProxyFactory(TObject realObject)
        : base(typeof(TObject))
    {
        this.RealObject = realObject;
    }


    private Func<Func<object>, object> _surroundDelegate;
    public TObject GetProxy(Func<Func<object>, object> surroundDelegate)
    {
        this._surroundDelegate = surroundDelegate;
        return (TObject)this.GetTransparentProxy();
    }

    public override IMessage Invoke(IMessage msg)
    {
        //Bu örnek gelen çağrımın bir metot olduğu varsayımı altında yapılmıştır.
        //Eğer çağrım bir Property ise ona göre bu kodu değiştirmek gerekir.Yani set_ ve get_ önekleri ile metodu dinamik bir şekilde çağırmak gerekir.

        IMethodCallMessage message = (IMethodCallMessage)msg;

        if (message != null)
        {
            //MessageBox.Show(message.MethodName + " metodu çağrılmak üzere. Biz araya girdik çağrılmadan önce");

            object methodRetval = _surroundDelegate(() => message.MethodBase.Invoke(RealObject, message.InArgs));

            ReturnMessage retVal = new ReturnMessage(methodRetval, null, 0, message.LogicalCallContext, message);

            return retVal;
        }
        return null;
    }
}

Burada göz atılacak 3 önemli satır var.

  1. 5 numaralı satır'da; bir nesnenin proxy'ini üretmek için ProxyGenerator sınıfını üretirken; gerçek nesneyi de vermeyi zorunlu tutuyoruz.
  2. 13 numaralı satırda method parametresi :"Func<Func<object>, object>". Yani içerisine object tipinde değer döndüren; verilen Delegate'i çalıştırıp, dönen değeri geri bize veren bir Delegate istenmektedir. Biliyorum cümle çok karmaşık oldu ama kod yeterince açık değil mi zaten :D
  3. 30 numaralı satırda ise; proxy nesne üzerinden çağrılan, gerçek sınıfın methodlarını çağırdığında GetProxy nesnesinde aldığımız delegate; içerisine gerçek nesnenin ilgili methodunu barındıran delegate verilerek çalıştırılıyor.
Son olarak da: Core Sınıfımızın son hali :
public static class Core
{
    public static IComplexService ComplexService
    {
        get
        {
            if (ConfigurationManager.AppSettings["useService"] == "0")
                return new ComplexService();
            //return new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService").CreateChannel();

            var proxyCreater = new ProxyFactory<IComplexService>(
                            new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService")
                                .CreateChannel()
                            );

            return proxyCreater.GetProxy(fnc =>
                {
                    using (OperationContextScope scope = new OperationContextScope(proxyCreater.RealObject as IContextChannel))
                    {
                        return fnc.Invoke();
                    }
                });
        }
    }
}
Proxy methodunu alırken Lambda Expression'lar gerçek methodu, OperationScope içerisinde gerçeklemiş oldum. İstersek, kendi case'lerimize özel çalışmalar da yapabiliriz.

Artık istediğimiz an basit bir konfigurasyon ayarıyla sistemimizi WCF üzerinden çalışır hale getirebiliriz. Üstelik servis method'larını çalıştırıken tekrar etmek zorunda kaldığımız kodları da merkezi noktalara çekebilmiş olduk.

Çalışan örneğin kaynak kodlarını buradan indirebilirsiniz.

Umarım fikrimi yeterince "Cin" bulumuşsunuzdur :)

Sıradışı günler, sıradışı başarılar dilerim.

[Tips & Tricks] İleri Visual Studio Teknikleri

sMerhaba Arkadaşlar;

Şimdiye kadar Visual Studio ile yazılım geliştirdik. Peki nimetlerinden ne kadar yararlanıyoruz? Daha doğrusu ne kadar farkındayız? Bu makalede sizlerle çok fazla seslendirilmeyen Visual Studio kullanım teknikleri ve VS Macro'lar üzerine konuşacağız.

Hızlı kod yazabilmek için temel gereksinim; editörü hızlı kullanabilmektir. Ne kadar hızlı mouse kulanırsak kullanalım, hiç bir zaman klavyede eriştiğimiz hızlara erişemeyiz( en azından benim ve çevremdeki arkadaşlar için böyle :). Bu da bizi Visual Studio kullanımında da klavye'ye yönelmemiz gerektiği gerçeğiyle karşılaştırır. O zaman hemen sık kullanılan Visual Studio Klavye Kısayollarına bakalım. Bunların broşür halinin şuradan da indirebilirsiniz.

  • Ctrl+. (Shift+Alt+F10un yaptığını yapıyor; using eklemek, gerektiğinde method oluşturmak vb. işlemlerde)
  • F12 - Go to Definiton
  • Alt+F12 - Find Symbol
  • Shift+Alt+F12 - Quick Find Symbol(Seçtiğin bir string'i Symbol olarak direk arar. En çok Web.Config gibi yerlerde işe yarıyor.)
  • Ctrl+Shift+F - Find In Files - Tüm bulduğu eşleşenleri liste halinde gösterir.
  • Shift+F12 - Find All References
  • Ctrl+Shift+A - Add New Item
  • Shift+Alt+C - Add New Class
  • Ctrl+W,S - Solution Explorer
  • Ctrl+W,E - Error List
  • Ctrl+F4 - Close Current Tab
  • Ctrl+Tab - Açık pencereler arasında dolaşmanı sağlıyor
  • Ctrl+ - : Bir kod satırından uzak bir satıra atladıysan Geri gelmeni sağlıyor. "Go to Definition" gibi atlamalarında da sayfalar arası atlama falan da yapabiliyorsun.(Navigate Backward)
  • Ctrl+Shift+ - : Navigate Forward
  • F7 - View Code  : Shift+F7 - View Designer
  • Ctrl+K, S  - Surround with (Snippet'le sorrund etmek için(#region,foreach,if vb.))
  • Ctrl+M,M - Bulunduğun bölümü collapse eder
  • Ctrl+M,O - Tüm bölümleri(region, method ne varsa) collapse eder.
  • Shift+F9 - Quick Watch
  • F9 - Toggle Break Point - Break point koyar.
  • Debug işlemlerinde F10,F11,Shift+F11,Shift+F5,F5 gibi bildiğiniz şeyler...

İhtiyaçlarınıza göre bu kısayolları ezberleyin derim. Kısa sürede kod yazma hızınızdaki artışı fark edeceksiniz. Çünkü mouse kullanımı etkileşimli(mouse'in ekranın neresine gittiğini görüp hızını ayarlamanız gerekmekte); ancak klavye kullanımı otonom(klavyeye bakmadan tuşlara basar ve istediğiniz sonucu alırsınız) bir harekettir. Klavye kullanımındaki otonom hareket, zihinizi kod yazarken mouse'den kurtarıp daha etkili kod yazmanızı sağlayacaktır.

Visual Studio'da Regular Expressions

Visaul Studio'nun çok fazla kullanılmayan nimetlerinden biri de Regular Expression'lar. Arama işlemlerinde işlerinizi ne kadar kolaylaştırdığını fark ettiğiniz de bilmeden geçirdiğiniz günlere acıyacaksınız.

Mesela kodlarınızdaki tüm tek satırda yazılan int propertyleri bulmak istiyorsunuz. Arama penceresinde "Use Regular Expressions" seçtikten sonra "int.*{.*}" yazmanız  yeterli :) Nasıl ama kolay değil mi? Ya da sık kullanabileceğimiz boş satırları silme işlemi için "\n:b*\n" aratıp, "\n" ile replace edebilirsiniz.":b" burada özel bir karakter kısmını ifade eder, tab ya da space.. * ise RegEx'den bildiğimiz şekilde çalışır: 0 ya da sonsuz tane tekrar..

Özellikle HTML ve XML kullanımlarında işinizi oldukça kolaylaştıracaktır. Find & Replace özelliğinde daha özel işler yapabilirsiniz de.. Mesela seçtiğiniz bir XML taginin başına ve sonuna özel bir tag ekleyebilirsiniz.

Burada önemli nokta Özel karakterlere hızlı erişim için arama textbox'ının yanındaki ">" butonunu kullanabilirsiniz. Diğer tüm anahtar karakterlere adresinden erişebilirsiniz.

Visual Studio Macros

Macro'lar tekrarlanan işler yaparken işlerimizi kolaylaştırmak için elimiz ayağımız oluyor. Visual Basic olması bir dezavantaj olsa da, online C#2Vb Code Converter'lar oldukça işinize yarayabilir.

2 türlü kullanabilirsiniz. Ctrl+Shift+R kısayolu ile geçici(temporary) Macro kaydedip, Ctrl+Shift+P ile de bu Macro'yu çalıştırabilirsiniz. Aynı zamanda bu kaydettiğiniz macroları Visual Basic kodu olarak da Macro Explorer üzerinden görüntüleyebilirsiniz. Sık kullandığım, ve bu kaydedilmiş Macro'lara bakarak oluşturduğum bir kaç Macro örneğini sunayım size:

 

IIS Worker Process'e Attach olmanızı sağlayan Macro Kodu

 

Sub AttachToW3wp()
Dim attached As Boolean = False
Dim proc As EnvDTE.Process

For Each proc In DTE.Debugger.LocalProcesses
If (Right(proc.Name, 8) = "w3wp.exe") Then
proc.Attach()
attached = True
Exit For
End If
Next

If attached = False Then
MsgBox("w3wp.exe çalışmıyor")
End If
End Sub


 



Aktif dosyayı sadce çalıştırıldığı anda göstern Macro Kodu(Bu özellik zaten Visual Studio'da var ama sürekli aktif olması dez avantaj olduğu için böyle bir çözüm güdülmüş. Ben de bu kodu başka bir yerde gördüm :)



 



Public Sub LocateFileInSolutionExplorer()
DTE.ExecuteCommand("View.TrackActivityinSolutionExplorer")
DTE.ExecuteCommand("View.TrackActivityinSolutionExplorer")
DTE.ExecuteCommand("View.SolutionExplorer")
End Sub


 



 



Açık olan tüm dökümanlara Format Document komutunu veren kod bloğu



 



Sub FormatEachOpenedPage()
For Each doc As Document In DTE.Documents
doc.Activate()
DTE.ExecuteCommand("Edit.FormatDocument")
doc.Save()
Next
End Sub


 



 



 



DB'de bir alandaki değeri çekip, bu veriyi bir dosya olarak Solution'a ekleyen Macro kodu.. Mail templateini DB'de tutan bir kod bloğu gördüm. HTML editör olmadığı için oldukça zor değiştiriliyordu. Bende Visual Studio üzerine çalışabileceğim bir ortam oluşturdum.



 



Sub LoadAllMail()
'Dim selectedfileName As String = DTE.ActiveDocument.Selection.Text
Dim adap As New OracleDataAdapter("SELECT * FROM CC_MAILTEMPLATE where ISACTIVE=1 MAILCODE IN (' + selectedfileName + ') ", Helpers.RealConStr)
Dim commandWin As EnvDTE.CommandWindow
commandWin = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindCommandWindow).Object

Dim dTable As New DataTable()
adap.Fill(dTable)

For Each row As DataRow In dTable.Rows
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("DBSources\" + Helpers.DefaultProject + "\MailTemplate").Select(vsUISelectionType.vsUISelectionTypeSelect)
Try
DTE.ItemOperations.AddNewItem("Visual C# Items\General\Text File", row("MAILCODE").ToString() + ".html")

DTE.ActiveDocument.Selection.SelectAll()
DTE.ActiveDocument.Selection.Delete()

DTE.ActiveDocument.Selection.Insert(row("BODY_TR_TR").ToString())
Catch ex As Exception
commandWin.OutputString("Yüklenemedi " + row("MAILCODE").ToString())
End Try

Next
End Sub


 



Alttaki de bu dosyadan tekrar veritabanına gönderen kod bloğudur.










Sub SaveMail()
DTE.ActiveDocument.Selection.SelectAll()
Dim name As String = DTE.ActiveDocument.Name.Split(".")(0)
Dim con As New OracleConnection(OttoHelpers.ConStr)
Dim cmd As New OracleCommand()
cmd.Connection = con
'
cmd.CommandText = "UPDATE CC_MAILTEMPLATE SET BODY = :MAILBODY WHERE MAILCODE='" + name + "' AND ISACTIVE=1"
cmd.Parameters.AddWithValue("MAILBODY", DTE.ActiveDocument.Selection.Text.ToString())
Try
con.Open()
cmd.Transaction = con.BeginTransaction()
Dim affectedRows As Int32 = cmd.ExecuteNonQuery()
If affectedRows = 1 Then
cmd.Transaction.Commit()
MsgBox("Güncellenen kayıt sayısı:" + affectedRows.ToString())
End If
Catch ex As Exception
cmd.Transaction.Rollback()
MsgBox("Transaction Geri Alındı (Rollback) !")
Finally
If con.State = ConnectionState.Open Then
con.Close()
End If
End Try
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
End Sub


Bu kodlar size de neler yapılabileceği ile ilgil oldukça iyi fikirler vermiştir diye düşünüyorum.




Umarım bu İp Uçları( [Tips & Tricks] ) işinize yarar ve size kolaylık sağlar.





Herkese iyi çalışmalar dilerim.

Verimlilik Teknolojileri Ne Kadar Verimli?

Merhaba Arkadaşlar,
Bugün sizlerle farklı bir konudaki fikirlerimi paylaşacağım.. Avrupa Birliği Enerji Verimliliği Etiket'leri.. Nam-ı diğer; 'Yeşil Teknoloji' reklamlarıyla alfabenin ilk bir harflerini yarıştıran reklamcılık malzemesi..

Geçen hafta aileme bir kurutma makinesi almaya karar verdik. Ünlü bir markanın üst sınıf diye tabir edilen modellerinde ikisini beğenmişler. Karar vermek için benim de fikrimi almaya karar vermişler. Tabi kısa süre sonra evlenecek biri olarak hemen incelemeye daldım :D
Öncelikle özelliklerine göz attım. Karşılaştırma matrisi genel olarak şöyleydi.

  • A Enerji sınıfı ürün
    • Orta-Üst sınıf teknik özellikler
    • Yaklaşık 120dk süren bir programı 1,5 kWh enerji harcıyor
    • Fiyat 1530 TL
  • B Enerji sınıfı ürün
    • Üst sınıf teknik özellikler(Daha geniş hacim ve daha çok teknoloji)
    • Yaklaşık 120dk süren bir programı 4,5 kWh enerji harcıyor
    • Fiyat 1180 TL
B sınıfı olan ürün daha çok imkan sunuyordu, üstelik ucuzdu da; ancak 3 kat daha fazla elektrik faturasına yansıması olacaktı. Düşündüm, ve kağıdı kalemi alıp hesaplamam gerektiğini anladım :) Biraz mühendislik yapmak gerekiyordu :P

Bizim evde haftada 2 kez cihazın çalıştırılacağını tahmin ettik. Yılın ortalama 6 ayı çamaşırları makinede kurutacaktık. Yıllık (26 Hafta x 2 Defa) = 52 kez cihaz çalıştırlacaktı. İnternet yaptığım kısa araştırma sonun 1 kWh saat elektriğin de 19,5 Krş yani 0,195 TL olduğunu öğrendim. Bu durumda cihazların elektrik faturasına yıllık ağırlığı aşağıdaki gibi olacak:

A Sınıfı Kurutma Makinası: 1,5 kWh * 2 saat * 52 kez * 0,195 TL = 30,42 TL
B Sınıfı Kurutma Makinası: 4,5 kWh * 2 saat * 52 kez * 0,195 TL =  91,26 TL

Yıllık masraf farkı yaklaşık 60 TL oluyor. 2 cihaz arasındaki fiyat farkının da 1530 TL - 1180 TL=350 TL olduğunu da dikkate alırsak A Enerji sınıfı cihaz daha düşük teknik özelliklerine rağmen, aradaki farkı ancak 6 yılda ödeyebiliyor ve sizi kâra geçirmeye başlıyor.

Bu durum A enerji sınıfı cihazın çok da tercih edilmesinin mantıklı olamayacağını görebiliyoruz.
Yukardaki hesaplamalar sizin diğer beyaz eşya tercihlerinizde de fikir verici olacağını umuyorum..

İnsan böyle bakınca; "Keşke hayat da matematiğe dökülebilseydi" diyor içinden :)

Hayatınızda "Akıllıca seçimler" dilerim..

15 Ocak 2009 Perşembe

NHibernate’e Başlama Klavuzu

Temeller

NHibernate kurumsal yazılım geliştirmede sıkça kullanılan açık kaynak kodlu bir Object-Relational Mapping(ORM) aracıdır.
ORM Nedir?
İlişkisel verileri, nesne tanımlarına dönüştürerek onlar üzerinde Nesneye Dayalı uygulama geliştirebilmemizi sağlayan araçlardır.
Bir ORM’in Üstlendiği Görevler Nelerdir?
· Temel Create-Read-Update-Delete fonksiyonlarını gerçekleştirebilmek için bir API
· Nesneler üzerinde sorgular oluşturabilmemiz için sağlanmış bir sorgu dili ya da bir API
· Mapping(Eşleme) tanımlarını yapabilmek için bir araç
· ORM gerçekleştirimi yapacak Transactional veri kalıcılığı, lazy-load ilişkilerin getirilmesi vb. işlemleri gerçekleştirecek bir framework…
Avantaj ve Dezavantajları
Avantajları:
  • Daha yüksek üretkenlik

    • Konsantrenizi CRUD işlemlerinden İş Mantığına yöneltebilmenizi sağlar.

6 Ocak 2009 Salı

Bir tutam staj; Bir tutam öğrencilik hayatı; Bir tutam vizyon

A Look to the Future by me®ve
Bugün sizlerle; değer verdiğim kardeşimlerimden biri; Cemile Arıkan ile, bir staj sorusuyla başlayan bir mail trafiğini paylaşacağım..
Yine gevezeliğim tututtu :) Telefonla başını şişiremediğim için; uzun uzadıya yazıp, gözlerini yormuş oldum :)
Sizin de kendinize dair bir şeyler bulabileceğinizi umut ettik. Cemile'nin de izniyle, bu mail trafiğini sizinle paylaşıyorum..
Not: Yazıda ismi geçen XYZ Firması Türkiye'de iyi tanınan; kurumsal bir holdingin, uluslarası bir firması.. Henüz toplum olarak; eleştiriyi kabul edebilecek kadar gelişmediğimiz için; firma ismini veremiyorum. Diğer yanda da elbette şu var: Ben daha iyisini yapmadan; birilerine taş atamam. Hele ki kamusal alanda :)

From: Cemile Arikan
To: Mustafa Çakmak
Subject: Merhabalar Hocam

Nasılsınız Hocam?
Neler yapıyorsunuz?
Inş herşey yolundadır, psikolojik fizyolojik:)

Fikirlerinizin bende önemli bir mahiyette olduğunu bildiğim için bir konuda fikrinizi rica edecektim. Kısaca genel bir malumat yapmak istiyorum; Aiesec’le(Yurtdışı Staj Hareketliliği) cebelleştiğimi hatırlıyorsun sanırım, geçen yaz olmadı, Erasmus sebebiyle işler çakıştı vs. Öyle olunca geçen yazım staj anlamında boş geçti.Bu yaz benim 3.5 ay staj yapmam lazimki (insss) dönem uzamasın, Bu yaz stajlarım bitmezse dönem uzar gibi birşeyler öğrendim ama tam emin değilim. Benimde düşüncem şimdiden Aiesec'le 3.5 aylık bir yer ayarlayayım, zaman uzun olduğu içinde 2 staj yerinede saydırayım(donanım-yazılım).Bu fikirle yola çıktım..Baya bir şirkete yazdım ,cevap gelenler arasında bir hazin sorun cıktı nasıl ki dersen; ilk gelen cevaplardan biri olan Nero’ydu, siteye baktım link felan vermemiş aiesec dedim, bu bizim bildiğimiz Nero heralde hemen olsun bitsin diye acele ettim, anlasmayı gönderdim ama ne oldu, sonra link verdiler bana bi baktım http://www.nero.pl/ bu adres çıktı, günlerce gözümün önünden o ana sayfadaki et resimleri gitmedi...ve istedikleri sey IT departmanındakilerle şirkete bir e-ticaret sitesi yapılması ve kulllandıkları teknoloji php5, OOP ve mysql vs…..zaten yazılımı mecburiyetten öğreniyorum gibi bir his var içimde….
Bu dönem hiç yazılım dersim yok ,öyle olunca iyice soğudum sanırım.Yani dedim artk mecburiyetten de olsa calışmayı bıraktığım yerden devam ettirmem gerekiyor diye düşündüm. Birşeyi çok içten yapmıyorsam; amaç işe yarar olmasıdır diye düşünüyorum.Yani eğer gerçek Nero olsaydı boyun büküp php ile uğraşıcaktım…Önceden de biraz bilgim vardı ,öyle gider diye düşünüyordum. Ama şimdi beklenen şirket olmadığı için php ile hiç uğraşmak istemiyorum. Sonra cevap gelen şirketlere tekrar bakmam gerekti. Kriter olarak kullanıkları teknolojı, şehir, ortam ,millet , benim görmek istediğim ülke vs vs ‘yi baz alarak iki şirket kafama takıldı. Birisi buydu; http://www.intersoftkk.com/english/index.html..%20sonraBuna ev halkı çok uzak dedi, bu sebebiyetle elendi.. Sonra o arada bir ukrayna şirketi vardı ; http://www.teaminternational.com/..Bak%C3%BC Bakü deneyiminden sonra burasıda biraz soğuk geldi ama hem dili tazelemek hemde kullandıkları teknoloji alanında ilerlemek istediğim için sıcak bakıyor gibiydim ama sadece mantıksal açıdan(ya duygularım :) .. Diğer bağlantı içinde olduklarımda askıda bekliyordu, aramızda duygusal bir bağ oluşmadığı için :( .. O arada bende Polonya'nın üzüntüsünü, Ukrayna ya hızlı cevap vererek atmak istedim ama simdi yine mutlu hissetmiyorum :( Şöyle ki; hani denir ya içim atmıyor diye, önemsediğim insanların fikirlerini duysam, fikirleri kıyas,olumlu olumsuz tabloları vs derken, bende daha net karar vereceğim deee çıkmazda kaldım şu sıralar sanırım...


İşin sorunu şuan illegal birşeyde yaptım. Polanya da anlaşmam varken Ukrayna'ya da mail attım :S ... Polonya'ya bir şekilde sorun bulup çıkmaya çalışacağım işin içinden… Bu arada Ukrayna için; bir iki ay Ukrayna da kalan arkadaşım vardı; o ortamı pek iyi anlatmadı, Gökalp te, sen bilirsin dedi, bende son olarak sana sormak istedim, senden sonra netten son bir araştırma yapıp onlara da ya kaçıyorum diyeceğim :) ya da şirketin cevabını bekleyeceğim, kabul edicekler mi diye.. Çünkü ben anlaşmamı göndersem bile onların hayır deme hakkı var: neden dersen ; onlar bana görev felan veriyor ,başarıyı görürlerse Skype'te mülakat yapıyorlar sonra alıyorlar. Şimdi bu Ukrayna'ya karşıda Bakü'den gelen bir millet soğukluğu hissediyorum, tek tatmin eden yanı CMMI Level 3 dereceleri var, istediğim teknolojiyi kullanıyorlar ve Microsoft teknolojileri için developer alacaklar. Senden ricam bir dost çerçevesinden iyi kötü tüm yorumlarını duymak istiorum.Umarım yeterince açık bilgi vermişimdir..Zamanının dar olduğunu biliyorum ama inan zaman veripte bu konuyla ilgili fikirlerini sunarsan beni çok müteşekkir edeceksin. Öte yandan bir konu daha var; uzaklık ,yakınlık, bilindik şirket, bilinmedik şirket, kullandığı teknoloji, veyaaaa boşver sen bunu gel Türkiyede iyi bir yer bul mu dersin… Bu açıları ve aklıma gelemeyenleri de düşünürsen çok çok mutlu olucam. Türkiyede de bu arada bir yakınımın ayarlarım dediği XYZ Firmasında şansım var şimdilik.. Durumlar böyle... Allah razı olsun hocam...


Sağlık, başarı, mutluluk ve bütün bunlar için farkındalık dolu günler diliyorum...



Simurg'a Doğru... / To the Eternal Life by me®ve
From: M. Tahir Çakmak
To: Cemile Arıkan
Subject: Re: Merhabalar Hocam


Merhabalar Cemile;

Teşekkür ederim, iyi olmaya çalışıyorum :)
Pek her şey yolunda değil; ama şimdilik mutluyum. Kendi düşen ağlamaz misali: psikolojik ve fizyolojik olarak kendimi güçlendirmeye çalışıyorum :)

Öncelik bana değer verip fikrimi sorduğun için çok teşekkür ederim. Gerçekten beni onurlandırdın...

Mailinin uzunluğundan; zor bir kararın önünde olduğunu anlayabiliyorum.
Her yönüyle tüm ayrıntılarıyla düşünülmesi gereken bir karar...

Konuya oldukça önemseyerek bakıyorum ben de.. Ancak düşünmem gerekiyor. Ciddi ve ayrıntılı biçimde.. Şu bir kaç gün bir miktar yoğun olacağım.
Bundan dolayı; bana kısa bir mühlet vermeni istiyorum.

Yine de şunu bilmeni istiyorum: Ben sana çözüm üretemem; hatta seçenek bile üretemem.
Sadece doğru soruları kendine sormana yardımcı olabilirim.

Ve bence ilk sorman gereken soru şu: "5 yıl sonra kim olmayı istiyorum? Hayallerim neler?"

Önümüzdeki 5 yıl boyunca; aldığın her bir nefes seni farklılaştıracak.
Ve muhtemelen; 5 yıl sonra bugün olmak istediğin kişi olmayı, istemeyeceksin. Çok farklı bir insan; hayallerinin dışında bir birey olacaksın. Ama olmayı isteyeceğin kişi olacaksın. Olmayı seveceğin Cemile..

Burada anahtar nokta şu ki: Hayat yeni Cemile'yi şekillendiririrken; hedeflerini günlük değiştiremezsin.
Evet mükemmel hayallere bir günde ulaşamazsın; ama sürekli değişen bir planla da her hangi bir yere gidemezsin.
"Hayal Eylem Planları"nı adım adım uygulayacaksın. "En kötü karar; karasızlıkdan iyidir", karasız kalırsan harekete geçemezsin.

Yaşamı ve kendini anlamaya çalıştığın; "İlim kendin bilmektir"i uygulamaya geçtiğin her nefeste, koşmaktan vazgeçmemelisin.
Korkudan uzak, cesur hayaller kurup; -yeni bir hayal ile bu hayallerini değiştirene dek- onlara doğru koşmalısın.

Koşmaktan vazgeçersen; "İlim öğrenmek"den koparsın.
Çünkü yaşam; kitaplara sırlarını aktaramaz. En fazla sırların yerlerini gösterebilir.

Yaşamın sırlarını öğrenmek için; bizzat yaşaman gerekli..

Tekrar görüşünceye kadar şimdilik benden bu kadar :)

Kendine çok iyi bak :)
Allah'a emanet ol..
Dua ile..

Küçük bir ip ucu daha: bütün yemeklerden tadımlık almak yerine bazılarını gerçekten ye.. Bir çok yemek gerçek tadını tabağındaki son lokmada verir.
Yaşam ayrıntılarda saklı - klişe ama çok doğru bir söz :)

Mustafa Tahir Çakmak


From: Cemile Arıkan
To: M. Tahir Çakmak
Subject: RE: Merhabalar Hocam

Merhabalar Tahir,

Gerçekten çok anlamlı bir maildi,gerek ihtiyaca binaen gerekse genel hayata binaen..

Hayata geçirmem gereken bir çok cümleyle yüzleşmek gerçeğin biraz zorlayan ta kendisi olmakla birlikte beni güzel bir ruh haline soktu,teşekkür ediyorum..

Kendini sıkıştırma müsait olabildiğin anı beklerim ben..

Allah'a emanet ol...



From: M. Tahir Çakmak
To: Cemile Arıkan
Subject: Re: Merhabalar Hocam


Merhabalar Cemile;

Mail geciktiği için kusura bakma.. Vakit bulamadım. Bu hafta zorunlu iznimiz var. Evde yeni işler yüklediler :)
Sabah kahvaltıdan sonra; mutfakta bulaşıklarla uğraşıyordum desem :)

Şimdi biraz evden 'kaçtım' :) Starbucks'tayım; elimde kahve, hafif bir müzik ve belki kafedeki 2-3 kişiden biriyim :)

Şimdi gelelim 'gerçek dünyaya'... Umarım bu mail çok gecikmemiştir...

Bu yaz staj yapmazsan okulun uzar. Bu konuda yapabileceğin şey; gerekiyorsa naylon staj yapmak. Ama ümidim o ki; lazım olmayacak ;)

Elindeki seçeneklere göz attığımızda
  • "Aisec ile" Ukrayna ya da -uzak olsa bile- Japonya..
  • Türkiye'de XYZ Firması gibi kaliteli -sanılan- bir yerde staj yapmak..
Başka seçenekler kısmına gelmeden şunlar hakkındaki soruları soralım mı?

Neden yurt dışı? Peki bu sebebi Ukrayna mı daha çok karşılıyor, Japonya mı?
Eğer yurt dışı sebeplerini engelleyen bişeyse uzaklık, Japonya'ya "Uzak" diyebilirsin; ama 'Yurt dışı amaçlarına' daha uygunsa, biraz daha uzağa gitmenin zararı olur mu?
Diğer taraftan; Ukrayna hakkındaki korkuların 'amaçlarına' zarar verir mi? Amaçlarını elde edememe ihtimalin olur mu?
İp ucu: Firmalar hakkında bilgi için sosyal platformları denedin mi? LinkedIn,Facebook, ya da Xing.. Dene, gerekiyorsa öz geçmişi hoşuna giden bir çalışanına da mesaj at.. Hatta bir kaç kişiye at; birisi döner her halde :)

Neden Türkiye? Neden XYZ Firması?
Bu soruya çok dikkatli cevap vermen gerekeceğini baştan söylemeliyim. Çünkü herkesin hayali olan -bu seni tatmin etmiyor olabilir; çünkü sen herkes değilsin- 'yurt dışı stajı'nı elinin tersiyle itmek olacak yaptığın..
Bu soru hakkında daha geniş düşünebilmen için bir kaç bilgi vermek zorunda kalacağım. Bunlar sadece kendi fikirlerim olacak.. Farklı düşünüyor olabilirsin.

Staj ya da yarı zamanlı çalışmak denilince aklıma 2 avantaj geliyor.
  1. Vizyon geliştirmek;
  2. Prestijli bir CV
Vizyon geliştirmek derken: İnsan ne kadar internetde dolaşıp tüm bilgilere ulaşabileceğini iddaa etse de; internet, bulabildiğimiz ölçüde bize vizyon verir. Yani Google'da arattığımız kelimeleri bir yerlerde görmeliyiz. 'Yazılım mühendisliği' kelimesini arattırdığımızda çıkacak milyonlarca web sayfasından, blogdan, istediğimiz kelimeyi bulmakta zorlanırız. Birilerinin bize -arada da olsa- kapıları göstermesi gerekir. 3. sınıfın sonlarındayken Özgür Altuntaş bize bir kaç dakika dahi olsa Netron Framework'u anlatmamış olsaydı; staja gelip de bazı şeyleri görmemiş olsaydık; LINQ'yu anlayamazdık. Hatta Entity Framework'u.. The Beer House projesinin kitabında NHibernate diye bir kelime gördüm. Ama üzerine yoğunlaşıp; ne işe yaradığını anlamam için; stajda bize 1 saat Netron Framework'ün anlatılması gerekiyordu. Hatta haftasonuna kadar her sabah ve akşam toplam 2 saat süren yollarda zeki bir insanla(Harun) tartışmam gerekiyordu.
Martin Fowler benim için 'gerçek bir üstad' olarak gözükmesi için; bize Netron'daki yazılım mimarı Mutlu Kaya'nın üzerimizdeki çabalarına ihtiyaç vardı. Çok katmanlı mimariyi 2 saat anlatmasıyla gelen bakış açısından oluşan "anahtar kelimeler"i Google ile birleştirerek ulaştığım bir adam Martin Fowler..

Bu açıdan güzel bir staj sana bunu verebilir.
Güzel bir staj kelimesini XYZ Firması asla karşılamayacaktır.
Bunların çeşitli sebepleri var. Öncelikli sebeplerden birincisi; sana ve senin değerlerine kesinlikle itimadı olmayan bir kurum. Baş örtünle işe gidemeyeceğin, namaz kılamayacağın -kılsan dahi, bir kaçak gibi merdiven boşlukların kılabileceğin- bir ortam. "İnsana vermediği değer"i anlatmayacağım bile... Çalışmak için kesin saatleri olan bir firmanın; zaten yaratıcılık denilen kavrama bakışı olmadığını bilmelisin.
Gelişim dediğimiz şey ise; mümkün olamayacaktır. Bu yüzden daha küçük bir firma sana iyi bişeyler verebilir. Ama en iyi seçenek şu; gir facebook'a; staj yapmak istediğin firmayı bul, bu firmada aktif olan bir kişiye mesaj at. Verdiği cevaptan nasıl bir insan olduğunu anlayacaksın zaten...
İnsan(staj sorumlun) herşeyden önemli bir kavram stajda. Ibm'de bile sana stajı zehir edebilir. Ya da devlet kurumunda mükemmel bir staj yapmanı sağlayabilir. Bu yüzden vizyonu olan bir adam bul, ve yanında staj yapmaya çalış derim.. Dünyanın neresi olursa olsun bu yer: ister, sizin sokağın 2 altındaki bir yazılımcı ofisi.. İsterse de, dünyanın en yüksek binsaındaki yazılımcı ofisi..

Şunu da söylemeliyim; Vizyonun yeterince genişlediğinde ama hala o vizyonu hayata geçirmediğinde; sana yeni vizyonun hiç bir yararı olmayacaktır.

Mesela yarı zamanlı çalışmaya başlamak yerine; -vizyonumun emrettiği- Java'yı daha sağlam öğrenseydim, bitirmeyi güzel bir şekilde bitirebilseydim, şu an çok daha farklı bir yerde olabilirdim. Bunu bugün daha net görebiliyorum.

Prestijli CV: Önemini sen benden daha iyi biliyorsun. Ama şunu söylemeliyim: Netron stajımın, Microsoft stajımdan katlarca daha iyi geçtiğini, çook daha fazla şey öğrendiğimi söylemeliyim. Yine de; beni işe alanların Microsoft stajıyla daha çok ilgilendiğini söylemek zorundayım :( Yurt dışı stajı muhtemelen prestijli bir CV kazandıracaktır. Ya da XYZ Firması stajı..

İpUcu:
Yerinde olsam; geçen sene bize "Ekip olmak ve Liderlik" konusunda seminer veren Reha Yurdakul'a mail atardım.(http://rehayurdakul.com/)

Başka bir konu da; " birşeyi çok içten yapmıyorsam amaç işe yarar olmasıdır" sözün..

Bana sorarsan "Bir işi içten yapmıyorsan yapmamalısın.." İllaki yapman gerekiyorsan; 'onu içselleştirmelisin'. "Sevmelisin. Hala içten değilsen, o zorunluluktan kurtulmak için ne gerekiyorsa yapmalısın..."

Eğer yazılım geliştirmeyi sevmiyorsan; yazılım geliştirmemelisin. Ama yazılım geliştirmenin 'sana uygun olduğu' olduğunu düşünüyor ama henüz sevmenin bir yolunu bulamadıysan; öncelikli olarak bu sorunu halletmelisin.

Sana mail yazmayı sevmeseydim; kesinlikle mail atmazdım. İnsanlara yardım etmeyi sevmeseydim; bana şu an sadece "Tahir Bey" diyor olurdun. Hatta cevap bile alamazdın muhtemelen...

Önce sevmelisin.. Ama şunu kesinlikle bil: "Sevmek bir duygu değil; bir eylemdir !"

Topkapı Sarayı - uzun ince bir yoldur hayat...
Etkili İnsanların 7 Alışkanlığından bir alıntı:

Bir gün Stephen R. Covey; bir seminer arasında; bir adam yanına yaklaşmış. Adam eşiyle ilişkisinden yakınmış. "Artık birbirimizi sevmiyoruz. Kavga falan ettiğimiz yok; sadece sevgimiz kalmadı.." diyor. Evlilik koçlarına falan gittiklerini ama hiç bir işe yaramadığını söylemiş. "Ne yapalım?" diye sormuş.

Covey; "Sevin onu !" demiş. Adam "ama o duygu öldü" diye cevaplayınca Bay Covey tekrarlamış; "Tamam o zaman; sevin onu. Sevmek bir duygu değil; bir eylemdir. İnsan, emek verdiği, zaman ayrıdığı, kendinden feragat ettiği şeyleri sever. Sevin onu !"...

Yani kodlamayı sevmek istiyorsan; yazılım geliştirmelisin. Vakit ayırmalısın, emek vermelisin..
İstediğin şey "yazılım geliştirmeyi sevmek ise"; onu "sevmelisin", "sevmek için harekete geçmelisin" :)
İstediğin başka bişeyse de onu "sevmelisin"..

Sevdiğin şeyi yap.
Hayat böyle anlamlı oluyor.

İyiliği dahi severek isteyerek yapmazsan; mutlu etmiyor insanı.. (Bizzat yaşadığım zamanlar oldu; kulübe yeni başladığım zamanlarda :)

O zaman sen de kendine sor:
Ne istiyorum? Neyi sevmek istiyorum?


Sevgi ve Saygılarımla;

Not: Bu yazdıklarım işine yaradığını düşünüyorsan; başkalarının da işine yarayacağını düşünüyorsan senin de izninle; blogumda yayınlamayı düşünürüm. İster isminle, ister isimsiz.. Ne dersin?
Not 2: Çok uzun yazdığım için atladığım bişeyler olabilir. Ya da imla hataları, hatta anlatım bozukluklukarı; kusuruma bakma :)

Mustafa Tahir Çakmak



From: Cemile Arıkan
To: M. Tahir Çakmak
Subject: RE: Merhabalar Hocam


'Merhaba'dan önce o güzel ve hür yüreğini tebrik etmek istiyorum. Ve ardından en içten sevgi ve saygımla ' Merhaba ' diyorum.

Öncelikle gecikme için estg. hiç sorun değildi , tahmin etmiştim yoğun olduğunu.. Ama bulaşık felan diye düşünmemiştim :D Şaka bir yana hayat mı yoksa insanlar mı orası tartışılır ama insan yeri geliyor her işi yapıyor cidden :)

Blogunda yayınlama kısmı içinde; inan benim işime çok yaradığını düşünüyorum, açıklamaları ilerleyen satırlarda yapacağım ne ve nasıl şekilde olduğuna dair.. Ve bende isterim ki diğer insanlarada birşeyler katsın, istediğin şekilde yayınlayabilirsin(insiyatif senin), benim için mahsuru olan bir mahremiyeti yok, daha ziyade diyalogta etkin bir psikoloji hazinesi var :)

Karar aşamasına gelince; düşündümde kararsızlık ve sorun , doğru sorular üretememekten dolayıymış... Sorularına biraz daha derinden odaklanmaya çalışıp cevaplarını çıkarınca, biraz daha sevdim ve yapmak istedim. Yurtdışında gerçekten sevebileceğim bir yer beni çok mutlu edecek diye düşünüyorum; sebeplerse çoook gerçekten;
Türkiyedeki düşüncesel baskı ortamı ,insanlar - işler - koşuşturmalar(beraberinde gelen sıkıcı stresli ortamlar)(Türkiye nin dezavantajları benim için..), öte yandan beni her zaman mutlu eden yenilik merakım(gerek insanlar gerekse kültürler ,tabiki her adımı bikaç kez düşünerek..)(buda benim için yurtışının sakin ortamı ve güzel bir avantajı) ,yurtdışının sakinliği bir nevi insanın kendisini nadasa bırakması gibi ve en önemlisi insanın kendisini uzaylı gibi hissetmemesi(şeklim şemalim …) , saygı görmesi (bugüne kadar çok şükür böyle gelebildik inş hep doğru insanlarla karşılaşırız..)...Birkaç aydır Erasmus'la Malta'da bulunmaktayım, herşeyden uzak sakin bir yaşantı,özlemişim gerçekten... İşte sebepler bu şekilde... Sanırım yazını bir kaç kez daha okuyacağım :) Değişen düşünceler ve gelişmelerle arada durumuma dair mailleri paylaşabilirim umarım ??

Benden de şimdilik bu kadar, tekrardan çok teşekkür ediyorum… Parmaklarına :) ve yüreğine sağlık..

Görüşmek üzere

Cemile

15 Aralık 2008 Pazartesi

Kurumsal Yazılım Geliştirme ve Visual Studio 2008

İş yerinde bilgi paylaşımı için hazırladığım sunumu sizlerle paylaşmak istedim... Kurumsal yazılım geliştirme teknikleri ve Visual Studio 2008'deki uygulamaları hakkında güzel bir özet durumunda...
İşinize yarayacağını umarım...

View more presentations from mtcakmak.

14 Kasım 2008 Cuma

Hayallerimiz; Bilinç Altı, Farkındalık, Zihin Oyunları

Bu sabah; iş yerine beraber geldiğimiz Mali İşlerdeki bir abla'ya "iş kurma" ile ilgili hayallerimi anlattım. Hayranlıkla dinledi beni.. Aslında istediği, beklediği bişey değildi.. Çok fazla sormadı da.. Ben küçük bir fikir belirttim; "Şunu nasıl yaptınız?" dedirterek ilgili olup olmadığını anlamaya çalıştım. Çünkü bazen gerçekten çok geveze oluyorum :) 

Koç olmak

Savaş Şakar'ın "Koçluk ve Saç Traşı" adlı yazısına yorum yazdım. Başarıyı formulize ettim:

[more]

Başarı = Okumak(Teorik)+ Okuduklarımızın doğruluğunu ispat etmek(Gözlemlemek) + İspat ettiklerimizi yapmak(Uygulamak, tecrübe etmek)

Onun -koç olmak konusuna çevirerek- cevabı dillere destan :)

Koç Olmak = Oku + Çevrendeki profesyonelleri gözlemle + Okuduklarını pratiğe nasıl aktarabileceğini düşün + uygula + başarılı olanları geliştir ve başkalarına aktar

7 Kasım 2008 Cuma

Ajax Teorisine Giriş ve Javascript Videosu (Webcast, Screencast)

"Bir de Ajax'ın teoriği mi vardı?" diye soranlarınızı duyuyor gibiyim...
Vardı hem de neler neler... 
Ajax Framework'ler keşfedilmeden önceki zamanlarda; Ajax ile çalışmak için, öncelikle Javascript ile tekerleği keşfetmeniz gerekirdi.. Sonra kalan parçaları da tek tek keşfettikten sonra bir arabaya sahip olabilirdiniz :) El yapımı araba ancak Serçedeskadar oluyordu. GMail bile o zamanlar 100 basamıyordu :)

6 Kasım 2008 Perşembe

Kurumsal Yazılım Geliştirmeye Giriş Videosu (Webcast, Screencast)

Öncelikle eski dökümanları girelim :)
Sakarya Üniversitesi Bilgisayar Kulübü Mail Grubu'ndaki arkadaşlar bilirler. Oraya daha önce göndermiştim. Hikayesini de burdan öğrensinler :D
Peki nedir bu videonun hikayesi: 3. sınıf 2. dönem(2007 Mayıs) kulüpteki işlerin üzerine biraz tembelliğim tutunca İnternet Programlama dersinin ödevini son haftasonuna kadar hazırlayamadım. Ödev teslim tarihinden 3 gün önceki son derste; Ümit Hocamız (Prof. Dr. Ümit Kocabıçak) ödevi hala yapmayanlara fırça kayıyrodu :) Tabi hem asp.net hem de php ile yapılacak bir e-ticaret sitesi örneği.. Son haftasonu bitmez ödev; adam haklı..

10 Kasım 2007 Cumartesi

İstanbulu sevmeye başladım...

Son iki-üç aydır; günlük olarak İzmit'den gidip geldiğim İstanbul yollarını yavaş yavaş sevmeye başladığımı itiraf etmeliyim...  Bir noktada çalışmak için mecburen taşınacak olduğum İstanbul şehri benim için gün geçtikçe bağlılık yaratmaya başladı...

3 Eylül itibariyle 3. stajıma(IBM Türkiye) da başlayacağım; ancak bu kadar güzel bir şehire yolculuk günlük 4 saatimi alacak olsa dahi kesinlikle buna değer bence... Size küçük de bir İstanbul hediyesi vereceğim. Ben de 2.0 Megapiksellik bir Telefonun bu kadar iyi bir kareyi çekebileceğine inanmıyordum ama çekti işte... Hayadarpaşa Tren Garı (Wallpaper için tıklayınız...)

photo by Tahir Çakmak

Microsoft Yazokulu'nun ardından

23 Temmuz - 17 Ağustos Tarihleri arasında katıldığım ve katılmaktan da oldukça keyif aldığım; Microsoft Yazokulu 2007 - İstanbul sonlandı. Oldukça güzel günler geçirdiğimiz YazOkulu'nda birbirinden kaliteli konuşmacıların katıldığı bir çok eğitim aldık.
Bunlardan bazıları:
  • Windows Server 2008 - Murat Bayraktar
  • Sql Server 2005 - Bülen Sözge
  • Asp.Net 2.0 - Aykut Taşdelen
  • .Net Framework 3.0 - Burak Sarica
[more]
  • Sharepoint 2007 - Onur Görür
  • Proje ve Uygulama - Mehmet Nuri Çankaya...
 
Önümüzdeki günlerde aldığımız derslerde tuttuğum notları sizlerle paylaşıyor olacağım.
 
Herkese iyi çalışmalar...:)
YazOkulu Ekibi

14 Ağustos 2007 Salı

C#'ta Otomatik Web Form Gönderimi - Form Submitting

Hakkında yazılarımı girmeye vaktim olmasa da halen devam etmekte olan Microsoft Yaz Okulu 2007 eğitimlerindeyim. Bu eğitimlerde tanıştığım İTÜ Bilgisayar Mühendisliğinden arkadaşım Hasibe Göçülü(Blog) ile beraber onun bitirme tezindeki bir ihtiyacı gidermeye çalıştık. Bunula ilgili tecrübelerimi aktaracağım... Sorun tam olarak şöyle: Elimizde yaklaşık 1000 tane Protein dizilimin bulunuyor. Bu dizilimlerin her birinin http://jafa.burnham.org/newSession.html adlı sitedeki bir forma gönderilip yaklaşık 5 dak sonra sayfaya gelen(30 sn'de bir otomatik sayfa yenileniyor.) XML cevaplarının linkinin yakalanması ve indirilmesi gerekliliğiydi.

[more]

Çözüm için öncelikle Windows Forms projesinde bir adet WebBrowser bileşeni atmayla başladık. Bileşendeki HTML'in içine sonradan gömemeceğimiz bir script tagı ve buton sayesinde DOM üzerinden belli field'leri doldurmayı ve formu 'Submit' etmeyi planlıyorduk. Amacımız muhtemel 'Cookie', 'Session' gibi ayrıntıların hazır olarak bizi ilgilendirmeden bileşeni yazmaktı. Harici bir .js dosyasını yükleyip içinde bulunan metod yardımıyla forma submit komutunu vermemize rağmen sistem bize cevap vermedi. Ardından sistemin ayrıntılarına inmeye karar verdik. Öncelikle Ethereal adlı 'Network Sniffer' programıyla form submit edilirken hangi verilerin gönderildiğini yakaladık. Ardından C#'ın içinde System.Net namespace'i altında bulunan HttpWebRequest ve HttpWebresponse nesenlerini kullanmaya kara verdik(Http protokolünün implementasyonu için kullanılacak temel nesnelerdir). Ancak işler tahmin ettiğimiz  kadar kolay olmadı. Webbrowser bileşeni ile sayfayı açtığımızda bir adet cookie oluşuyordu. Bunu Http Header'ları arasına gömmüş olsak da sistem çalışmadı. Bir ayrıntı daha olduğunu anladık.(Bu arada cookie server'dan gelen bir 'Set-Cookie' komutuyla çalışmak yerine 'http://www.google-analytics.com/urchin.js' şeklinde bir adresten çektiği javascript dosyası ile oluşturuyordu. Mecburen de bu javascirpt'in derlenmesi ve cookie'nin oluşması gerekiyordu. Bu yüzden webbrowser bileşeni üzerinden çalışmaya devam ettik) Hasibe Content-Type header'inin yanında bulunan boundary ile başlayan bir satırdaki rakam ile gönderilen veride her satırda bulunan rakamın aynı olduğunu farketti. Sonuç başarılıydı. Karşı tarafatan beklediğimiz zaten sadece bir querystring idi. Bunu da yakalamış olduk Ethereal ile yakalanan veri yaklaşık şöyleydi. TCP       Kodları merak edenleriniz oldu tabi... Aşağıda...  

HttpWebRequest hWebReq = (HttpWebRequest)HttpWebRequest.Create(http://jafa.burnham.org/newSession.html);

HttpWebResponse hWebResp;

hWebReq.Method ="POST";

hWebReq.Referer =http://jafa.burnham.org/newSession.html;

//7d714.. şeklinde bilgileri de içeren yukarda belirtilen dosya, formun submit edilme anında ethereal ile yakalanmış

byte[] bf = File.ReadAllBytes(@"C:\myReq.txt");

hWebReq.ContentLength = bf.Length;

hWebReq.ContentType = "multipart/form-data; boundary=---------------------------7d7148ee0142";// Son Bulunan Nokta

hWebReq.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*";

hWebReq.Headers.Add("Cookie", webBrowser1.Document.Cookie);

hWebReq.GetRequestStream().Write(bf, 0, bf.Length);

hWebResp = (HttpWebResponse)hWebReq.GetResponse();

Stream str = hWebResp.GetResponseStream();

byte[] buf = new byte[20000];

//İlk oluşturmada string nesnesinin bir sorunu vardı; tüm bilgileri koyamadık; bu yüzden multiline bir textBox'ın içerisine 2 defada veriyi bastık, sonra geri aldık. O yüzden 2 defa tekrarlanıyor.str.Read(buf, 0, buf.Length);

str.Flush();

textBox1.Text = Encoding.ASCII.GetString(buf);

buf.Initialize();

str.Read(buf, 0, buf.Length);

textBox1.Text += Encoding.ASCII.GetString(buf);

string strPage = textBox1.Text;

string substrP = strPage.Substring(strPage.IndexOf("/result.html?ID="),"/result.html?ID=d398f118d3100146de4252289e68432a".Length );

substrPage = substrP.Substring("/result.html?ID=".Length, 32);

textBox2.Text = substrPage; 

string strur = "http://jafa.burnham.org/result.html?ID=" + substrPage;

webBrowser2.AllowNavigation = true;

webBrowser2.Navigate(strur);

6 Temmuz 2007 Cuma

IBM'den Innovasyon Dersleri

Radikal İşbirliği

IBM’in Yenilik Üretme Fabrikasından Dersler

2003’ün sonlarına doğru IBM’de veriler 3 yıl önce 5 Milyar Dolar yatırılan Chip işinin çok iyi gitmediğini gösteriyordu. 2002’de 1 Milyar Dolar kaybedilmişti; 2003’te de 252 Milyon($) da cabasıydı. İş işten geçmeden bir şeyler yapılmalıydı…

IBM yeni bir strateji yapmayı planladı. Çeşitli partnerleriyle toplanıp işbirliği yapmayı düşündü. Böylece beyin gücü paylaşımı ile bir yenilikçilik trendi ortaya çıkabilirdi. Küçük ortaklar ile başlayan bu işbirliği fikri piyasanın en büyük firmalarının beraber Ar-Ge işleri yapma fikrini ortaya çıkardı. Chip Ar-Ge’sinde içinde içlerinde AMD, Sony, Toshiba, Freescale gibi 9 firmanın bulunduğu bir “Açık Ekosistem” oluşturdu.

[more]

Bir çok büyük firma 21. yüzyılın  “Yenilikçi Ağları” denilen; diğer firmalarla takım çalışması yapmak zorunda kalınacağını düşünüyor. Elbette ki bir-boyutlu-herkese-uyar bir işbirliği söz konusu değildir. Her halükarda bu büyük bir risktir. Ama aynı zamanda da büyük bir şanstır. Bu yöntemle ulaşılan bazı önemli sonuçlar: Boeing’in yeni 787 Dreamliner’ı markete 12 ay önce koyabilmesine; P&G’nin Ar-Ge üretkenliğini %60 arttırmasını sağladı.

7 yıl önce IBM’in New York Hudson Vadisindeki chip fabrikası durma noktasında gelmişti. Şuanda ise hummalı bir çalışma altında… 200.000 çalışan bulunduğu fabrikaya şimdiye kadar 4.4 Milyar Dolar yatırım yapıldı. Bu dev maliyet, ve çalışma ödülleri beraber paylaşılıyor. IBM bu beraberliklerde fabrikanın yapımının paylaşılmasında 2 Milyar Dolar tasarruf etti, Bu beraberliklerin önümüzdeki 3 yıl içinde de 7 Milyar dolar fazladan kar sağlayacağı planlanıyor.

IBM’e göre dönüş yok. Ama hala bir çok Ar-Ge Lideri “Açık Yenilikçilik” fikrini yeni ve riskli buluyor. Açık Yenilikçilik’in gücü onların da böyle bir organizasyona katılmak zorunda kalacaklarını gösteriyor. Ama katılana kadar çok geç kalmış olabilirler.

BussinessWeek

Çeviri ve Özet: M. Tahir Çakmak