https://www.buraksenyurt.com/Burak Selim Şenyurt - Team Foundation Server2016-08-08T07:31:13+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/TFS-Version-Control-Hizmetine-Kisa-Bir-BakisTFS Version Control Hizmetine Kısa Bir Bakış2013-11-03T14:58:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p><strong>TFS Web Services </strong>kullanımlarını incelediğimiz <a href="https://www.buraksenyurt.com/post/TFS-Web-Services-ve-Kullanimi" target="_blank">bu</a> yazımızda, en popüler hizmetlerden birisi olan <strong>Work Item Tracking</strong> servisine odaklamıştık. Bu servisten yararlanarak özellikle template bazlı öğelerin<em>(Task, Bug, Product Back Log Item gibi) </em>nasıl okunabileceğini öğrenmiştik. Çok doğal olarak daha pek çok servis kullanımı söz konusu. Önemli olan nokta, ilgili servislerin <strong>TFS Client Object</strong> <strong>Model</strong> üzerinden kullanılabileceğidir.</p>
<p><span style="color: #ff0000;">[Yazı, Team Foundation Server 2012 üzerinde ele alınmıştır]</span></p>
<p>İşte bu yazımızda başka bir servis kullanımını incelemeye çalışıyor alacağız. Amacımız <strong>Version</strong> <strong>Control</strong> hizmetini ele alarak bir <strong>Team</strong> <strong>Project</strong> içerisinde yer alan ve <strong>Source</strong> <strong>Control</strong>’e dahil edilmiş çeşitli içerikleri elde edebilmek. Ağırlıklı olarak kod dosylarını görmeyi hedefliyoruz.</p>
<p>Örneğimizi bir <strong>Windows</strong> <strong>Forms</strong> uygulaması olarak geliştirebiliriz. Dilerseniz hiç vakit kaybetmeden ilgili <strong>TFS</strong> <strong>Assembly</strong> dosyalarını referans ederek işe başlayalım.<em>(Tabi kaynak kodun versiyon kontrolü denilince aklımıza aşağıdakinden daha iyi bir çözüm geliyordur diye var sayıyorum)</em></p>
<p><a href="https://www.buraksenyurt.com/pics/versioncontrolfunny.png"><img style="margin: 4px 0px; display: inline;" title="versioncontrolfunny" src="/pics/versioncontrolfunny_thumb.png" alt="versioncontrolfunny" width="640" height="230" /></a></p>
<h1>Başlangıç</h1>
<p>İlk olarak uygulamaya <strong>Microsoft.TeamFoundation.Client</strong>, <strong>Microsoft.TeamFoundation. Common </strong>ve <strong>Microsoft.TeamFoundation.VersionControl.Client</strong> <strong>assembly</strong> kütüphanelerini referans ederek işe başlayabiliriz. Örneğimize konu olan <strong>VersionControlServer</strong> tahmin edileceği üzere <strong>Microsoft.TeamFoundation.VersionControl.Client assembly</strong>’ ının bir parçasıdır.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsvc_1.png"><img style="margin: 4px 0px; display: inline;" title="tfsvc_1" src="/pics/tfsvc_1_thumb.png" alt="tfsvc_1" width="324" height="417" /></a></p>
<p>Uygulamamıza ait <strong>Form</strong> ise aşağıdaki gibi tasarlanabilir.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsvc_2.png"><img style="margin: 4px 0px; display: inline;" title="tfsvc_2" src="/pics/tfsvc_2_thumb.png" alt="tfsvc_2" width="638" height="618" /></a></p>
<p>Kullanıcılar <strong>app.config</strong> dosyasında belirtilen <strong>TFS</strong> sunucusuna bağlanabilecektir. Bu <strong>TFS</strong> sunucusu çok doğal olarak kendi içerisinde n sayıda <strong>Team Project Collection</strong> barındırabilir. İlgili <strong>Team</strong> <strong>Project Collection</strong>’ a ait bazı bilgilerin <strong>Collections</strong> bileşeni yanındaki <strong>ComboBox</strong> kontrolüne doldurulması sağlanmalıdır. Kullanıcı, bir <strong>Team</strong> <strong>Project</strong> <strong>Collection</strong> seçimi yaptığında ise, buna bağlı <strong>Team</strong> <strong>Project</strong> listesinin de ilgili <strong>ComboBox</strong> kontrolüne eklenmesi gerekmektedir. En azından bağlı olan <strong>Team</strong> <strong>Project</strong> adlarının listelenmesi gerekir. Kullanıcının yapacağı bir diğer seçim de, <strong>source</strong> <strong>control</strong> üzerinden çekilmek istenen dosyaların tipleridir. Örneğin <strong>C#</strong> , <strong>VB</strong> gibi kod dosyaları olabileceği gibi, <strong>XAML</strong> içerikli dosyalara da bakılmak istenebilir. Örnekte kısıtlı bir küme kullanılmıştır ancak bu genişletilebilir.</p>
<blockquote>
<p>Kendi çalışmalarınızı yaparken Team Foundation Server’ ın tfs.visualstudio.com adresinden sunulan hizmetini göz önüne almanızı ve o ortamda sunulan Code penceresini incelemenizi öneriririm. Code penceresine gelindiğinde aslında bu, bir Team Project Collection’ daki bir Team Project içerisindeyiz anlamına gelir. Dolayısıyla bu Team Project içerisindeyken source control üzerine atılan ne kadar içerik varsa görülebilir. Biz çok daha kısıtlı bir örneğini yapıyoruz. Aslında kapıyı azcık aralamak niyetindeyiz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsvc_5.png"><img style="margin: 4px 0px; display: inline;" title="tfsvc_5" src="/pics/tfsvc_5_thumb.png" alt="tfsvc_5" width="600" height="428" /></a></p>
</blockquote>
<p>Dosya tipi seçimi de belli olduğunda liste kontrolüne, söz konusu uzantıya sahip dosyaların bazı bilgileri gelecektir. Eğer herhangibir dosya seçilirse de, bu dosyanın içeriği gösterilecektir.</p>
<h1>Yardımcı Sınıflar</h1>
<p>Örnekte işleri biraz olsun kolaylaştırmak adına iki yardımcı <strong>POCO<em>(PlainOldClrObject)</em> </strong>tipi kullanılmıştır. Bu tipler içerisinde bir <strong>Team Project Collection</strong>’ ın ve <strong>Change Set</strong>’ in temel bilgileri tutulmaktadır.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsvc_3.png"><img style="margin: 4px 0px; display: inline;" title="tfsvc_3" src="/pics/tfsvc_3_thumb.png" alt="tfsvc_3" width="512" height="216" /></a></p>
<p><strong>TeamCollection</strong> sınıfı içeriği;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace HowTo_TFSVersionControl
{
public class TeamCollection
{
public string DisplayName { get; set; }
public Guid Id { get; set; }
public override string ToString()
{
return string.Format("[{0}]-{1}", Id.ToString(), DisplayName);
}
}
}</pre>
<p>ve <strong>ChangeSetItem</strong> sınıfı içeriği;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using Microsoft.TeamFoundation.VersionControl.Client;
namespace HowTo_TFSVersionControl
{
public class ChangeSetItem
{
public ItemType ItemType { get; set; }
public string ServerItem { get; set; }
public int ItemId { get; set; }
public int ChangeSetId { get; set; }
public override string ToString()
{
return string.Format("[{0}]-[{1}]-{2}"
, ChangeSetId.ToString()
, ItemId.ToString()
, ServerItem);
}
}
}</pre>
<h1>Kod Tarafı</h1>
<p>Dilerseniz öncelikle <strong>Form1</strong>’ e ait kod içeriklerini üretelim ve neler yaptığımızı açıklamaya çalışalım.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Windows.Forms;
namespace HowTo_TFSVersionControl
{
public partial class Form1
: Form
{
#region Common Fields
TfsTeamProjectCollection tfs = null;
VersionControlServer vcServer = null;
ItemSet itemSet = null;
List<ChangeSetItem> csitems = null;
IReadOnlyCollection<CatalogNode> teamCollectionNodes = null;
TfsTeamProjectCollection selectedCollection = null;
#endregion Common Fields
public Form1()
{
InitializeComponent();
cmbFileTypes.Items.Add("cs|C# Files");
cmbFileTypes.Items.Add("vb|Visual Basic Files");
cmbFileTypes.Items.Add("xaml|XAML Files");
txtTFSAddress.Text = ConfigurationManager.AppSettings["TfsAddress"];
FillTeamCollections();
}
private void FillTeamCollections()
{
tfs = new TfsTeamProjectCollection(new Uri(txtTFSAddress.Text));
teamCollectionNodes=tfs.ConfigurationServer.CatalogNode.QueryChildren(
new[] {CatalogResourceTypes.ProjectCollection },
false,
CatalogQueryOptions.None);
foreach (var teamCollectionNode in teamCollectionNodes)
{
TeamCollection teamCollection = new TeamCollection();
teamCollection.DisplayName= teamCollectionNode.Resource.DisplayName;
teamCollection.Id = Guid.Parse(teamCollectionNode.Resource.Properties["InstanceId"]);
cmbTeamCollections.Items.Add(teamCollection);
}
}
private void lstItems_SelectedIndexChanged(object sender, EventArgs e)
{
ChangeSetItem selectedChangeSetItem=lstItems.SelectedItem as ChangeSetItem;
Item item=vcServer.GetItem(selectedChangeSetItem.ItemId, selectedChangeSetItem.ChangeSetId);
using(Stream stream = item.DownloadFile())
{
using(StreamReader reader = new StreamReader(stream))
{
txtItemContent.Text=reader.ReadToEnd();
}
}
}
private void cmbTeamCollections_SelectedIndexChanged(object sender, EventArgs e)
{
cmbTeamProjects.Items.Clear();
lstItems.Items.Clear();
TeamCollection selectedTeamCollection=cmbTeamCollections.SelectedItem as TeamCollection;
selectedCollection=tfs.ConfigurationServer. GetTeamProjectCollection(selectedTeamCollection.Id);
var teamProjectNodes=selectedCollection.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.TeamProject },
false, CatalogQueryOptions.None);
foreach (var teamProjectNode in teamProjectNodes)
{
cmbTeamProjects.Items.Add(teamProjectNode.Resource.DisplayName);
}
}
private void cmbTeamProjects_SelectedIndexChanged(object sender, EventArgs e)
{
lstItems.Items.Clear();
txtItemContent.Clear();
vcServer=selectedCollection.GetService<VersionControlServer>();
string itemPath = string.Format("$/{0}/*.{1}"
, cmbTeamProjects.SelectedItem
,cmbFileTypes.SelectedItem.ToString().Split('|')[0]);
itemSet = vcServer.GetItems(itemPath, RecursionType.Full);
csitems = new List<ChangeSetItem>();
foreach (Item item in itemSet.Items)
{
ChangeSetItem csi = new ChangeSetItem();
csi.ItemId = item.ItemId;
csi.ChangeSetId = item.ChangesetId;
csi.ItemType = item.ItemType;
csi.ServerItem = item.ServerItem;
lstItems.Items.Add(csi);
}
lblStatus.Text = itemSet.Items.Length.ToString();
}
}
}</pre>
<p><strong>TFS</strong> üzerindeki <strong>Collection</strong> nesnelerini elde etmek için <strong>TfsTeamProjectCollection</strong> örneği üzerinden önce <strong>ConfigurationServer</strong>, ardından da <strong>CatalogNode</strong> özelliğine gidilmekte ve <strong>Child</strong> <strong>Node</strong> içerikleri sorgulanmaktadır. Bu sorgu içerisinde <strong>CatalogResourceTypes</strong> <strong>enum</strong> sabitinin <strong>ProjectCollection</strong> değeri kullanıldığından, <strong>TFS</strong> sunucusu üzerindeki <strong>Team</strong> <strong>Project</strong> <strong>Collection</strong>’ ların içerikleri elde edilir.</p>
<p>Bir <strong>Team</strong> <strong>Project</strong> <strong>Collection</strong> sorgulanırken <strong>Guid </strong>tipinden olan <strong>ID</strong> değeri önem arz eder. Bu yüzden sorgu sonucu elde edilen <strong>Node</strong>’ lar arasında dolaşılırken <strong>Resorce</strong> özelliklerinden yararlanılarak iki değerin alınması sağlanmıştır. <strong>DisplayName</strong> ve <strong>Properties[“InstanceId”]</strong> yardımıyla <strong>Team</strong> <strong>Project</strong> <strong>Collection’</strong> ı benzersiz olarak niteyen <strong>Guid</strong> değeri. İlgili özelliklerin toplandığı <strong>TeamCollection</strong> nesne örnekleri de <strong>cmbTeamCollections</strong> isimli <strong>ComboBox</strong> kontrolünün <strong>Items</strong> koleksiyonuna eklenmektedir.</p>
<p>Kullanıcı bu <strong>ComboBox</strong> bileşeninden bir öğe seçtiğinde ise, ilgili <strong>Team Project</strong> <strong>Collection</strong> altındaki <strong>Team</strong> <strong>Project</strong> örneklerinin, en azından adlarının çekilmesi gerekmektedir. Nitekim bu <strong>Team Project </strong>adı ilgili <strong>Version</strong> <strong>Control</strong> servisi tarafından, <strong>Change Set </strong>öğelerinin çekilmesi sırasında ele alınacaktır.</p>
<p>Seçilen öğenin karşılığı olan <strong>TfsTeamProjectCollection</strong> nesnesine ulaşmak için <strong>ConfigurationServer</strong> örneğine ait <strong>GetTeamProjectCollection</strong> metoduna başvurulur. Bu metod parametre olarak seçili öğenin <strong>Id</strong> değerini alır. Tahmin edeceğiniz üzere bu değeri, <strong>ComboBox</strong> içerisinde <strong>TeamCollection</strong> nesne örneklerinde birer özellik olarak kullanmıştık. Seçilen öğenin karşılığı olan <strong>TfsTeamProjectCollection</strong> yakalandıktan sonra ise <strong>CatalogNode</strong> üzerinden tekrar <strong>Child Node</strong>’ lara gidilecek şekilde bir çağrı yapılır.</p>
<p>Lakin bu kez <strong>CalatogResourceTypes</strong> <strong>enum</strong> sabitinin <strong>TeamProject</strong> değeri kullanılır. Buna göre seçili olan <strong>Team Project Collection</strong>’a bağlı olan <strong>Team</strong> <strong>Project</strong> listesi, birer <strong>CatalogNode</strong> olarak elde edilebilir. Sonrasında ise liste dönülür ve her bir <strong>Team Project</strong>’ in <strong>Resource </strong>özelliği üzerinden yakalanacak <strong>DisplayName </strong>değeri, <strong>cmbTeamProjects </strong>bileşeninin <strong>Items</strong> koleksiyonuna eklenir.</p>
<h1>Version Control Servisinin Çalışması</h1>
<p>Yazımıza konu olan <strong>Verison</strong> <strong>Control</strong> servisi ise bu noktadan sonra devreye girecektir. İlgili servis örneği kullanıcının yaptığı <strong>Team</strong> <strong>Project</strong> seçimi sonrasında önemlidir. Nitekim <strong>Change Set</strong> veri içeriklerinin elde edilmesi için ilgili operasyon desteğini sunmaktadır.</p>
<p>İlk olarak güncel <strong>Team</strong> <strong>Project</strong> <strong>Collection</strong> tespit edilerek generic <strong>GetService</strong> metoduna bir çağrıda bulunulur ve <strong>VersionControlServer</strong> tipinden bir referans alınır. Bu referansın <strong>GetItems</strong> metodu kilit noktamızdır. İlk parametre ile bir <strong>string</strong> verilmektedir ama yazım şekli özeldir.</p>
<p><strong>$/{0}/*.{1}</strong></p>
<p>ifadesinde <strong>{0}</strong> yerine <strong>Team</strong> <strong>Project</strong> adı, <strong>{1}</strong> yerine ise talep edilen dosya formatının uzantısı gelir. <strong>GetItems</strong> metodu esas itibariyle bir <strong>ItemSet</strong> örneği döndürür ve aslında beklediğimiz dosyalar bu tipin <strong>Items</strong> koleksiyonunca alınır. Örnekte <strong>Items</strong> özelliği dolaşılmakta olup her biri için bir <strong>ChangeSetItem</strong> örneklenir. <strong>ChangeSetItem</strong> sınıfında bir kaç temel özellik bulunmaktadır. <strong>ItemId</strong>, <strong>ChangeSetId</strong>, <strong>ItemType</strong> ve <strong>ServerItem</strong>.</p>
<p>Bu aşamadan sonra kullanıcının bir <strong>ChangeSetItem’</strong> ı listeden seçmesi halinde içeriğinin gösterilmesi adımına gelinir. Bu sefer de <strong>VersionControlServer</strong> örneğine ve <strong>GetItem</strong> isimli metoduna başvurulur. Örnekte <strong>GetItem</strong> metoduna iki parametre girmektedir. <strong>Item</strong> ve <strong>Change Set</strong> numaraları. Çok doğal olarak bir <strong>Change Set</strong> altında farklı numaralara sahip birden fazla öğe yer alabilir. Bu sebepten hangi <strong>Change</strong> <strong>Set</strong>’teki hangi öğeyi alacağımızı bildirmemiz gerekir.</p>
<p>Elde edilen <strong>Item</strong> öğesinin <strong>DownloadFile</strong> isimli bir fonksiyonu da bulunmaktadır. Bu metod sayesinde, sunucudaki içeriğin <strong>Stream</strong> olarak elde edilmesi mümkündür. Örnek kod parçasında <strong>StreamReader</strong> sınıfından yararlanılmış ve ilgili sunucu içeriğinin <strong>txtItemContent</strong> isimli <strong>TextBox</strong> kontrolüne basılması sağlanmıştır.</p>
<h1>Çalışma Zamanı Sonuçları</h1>
<p>Örneği çalıştırdığımızda ve sırasıyla <strong>Team Project Collection</strong>, <strong>File Type</strong> ve <strong>Team Project</strong> seçimlerine yaptığımızda, aşağıdakine benzer sonuçlar ile karşılaşabiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsvc_4.png"><img style="margin: 4px 0px; display: inline;" title="tfsvc_4" src="/pics/tfsvc_4_thumb.png" alt="tfsvc_4" width="640" height="620" /></a></p>
<p>Dikkat edileceği üzere <strong>Default</strong> <strong>Collection</strong> altındaki bir <strong>Team Project</strong>’ in içerisinde yer alan <strong>C# </strong>kod dosyalarının temel bilgileri çekilebilmiştir. Bu bilgiler arasında, <strong>Item</strong> ve <strong>Change Set</strong> numarası ile <strong>Server</strong> üzerinde tutulan <strong>Full Path</strong> bilgisi yer almaktadır. Hatta istenirse son <strong>Check-In</strong> bilgisi bile alınabilir<em>(Belki de alınamaz. Neden araştırmıyorsunuz <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_197.png" alt="Winking smile" />)</em> İşin güzel yanı söz konusu öğelerden herhangibirisine tıklandığında, içeriğinin de görüldüğüdür.</p>
<h1>Uygulamada Neleri Yapmadık?</h1>
<p><strong>Version</strong> <strong>Control</strong> hizmetini kullanarak, <strong>Source</strong> <strong>Control</strong> içeriğini çekelebilmek oldukça kolaydır. Bu felsefeden yola çıkarak kendi Source Control arabirimlerinizi yazabilirsiniz. Örneğin <strong>Windows Phone</strong> tabanlı çalışacak bir istemci söz konusu olabilir. Yani mobil bir cihazdan Source Control üzerindeki hareketlilikleri takip edebilirsiniz. Pek tabi yapabileceğimiz daha pek çok şey var. Örneğin,</p>
<ul>
<li>Source Control’ den çekilen bir içeriği güncelleyebilir ve sunucuya kaydedebiliriz.</li>
<li>Yeni bir öğeyi Source Control’a ekleyebiliriz.</li>
<li>Bir öğeyi silebiliriz.</li>
<li>Klasör veya Branch gibi öğeler oluşturabiliriz.</li>
</ul>
<p>ve benzerleri…</p>
<p>Bu konuları örneğimizde ele almadık ancak <strong>VersionControlServer</strong> tipinin işaret ettiği servis metodlarını inceleyerek nasıl yapabileceğinizi araştırmaya başlayabilirsiniz. Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2013%2f3%2fHowTo_VersionControl.zip">HowTo_VersionControl.zip (218,31 kb)</a></p>2013-11-03T14:58:00+00:00tfsteam foundation serverclient object modeltfs servicesxml web serviceversion controlbsenyurtTFS Web Services kullanımlarını incelediğimiz bu yazımızda, en popüler hizmetlerden birisi olan Work Item Tracking servisine odaklamıştık. Bu servisten yararlanarak özellikle template bazlı öğelerin(Task, Bug, Product Back Log Item gibi) nasıl okunabileceğini öğrenmiştik. Çok doğal olarak daha pek çok servis kullanımı söz konusu. Önemli olan nokta, ilgili servislerin TFS Client Object Model üzerinden kullanılabileceğidir.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=584445d8-da65-4278-a703-f729075800c02https://www.buraksenyurt.com/trackback.axd?id=584445d8-da65-4278-a703-f729075800c0https://www.buraksenyurt.com/post/TFS-Version-Control-Hizmetine-Kisa-Bir-Bakis#commenthttps://www.buraksenyurt.com/syndication.axd?post=584445d8-da65-4278-a703-f729075800c0https://www.buraksenyurt.com/post/TFS-OData-DestegiTFS OData Desteği2013-08-25T10:35:00+00:00bsenyurt<p><span style="color: #ff0000;"><a href="https://www.buraksenyurt.com/pics/almworld.jpg"><img style="float: right; margin: 4px 0px; display: inline;" title="almworld" src="/pics/almworld_thumb.jpg" alt="almworld" width="300" height="231" align="right" /></a>[Orjinal Yazım Tarihi 3/20/2013]</span></p>
<p>Merhaba Arkadaşlar,</p>
<p>Çoğu zaman geliştirilen yazılım ürünleri ile farklı profilden insanları ortak bir payda da buluşturmayı hedefleriz. Farklı özelliklere sahip insanları, ürüne nasıl katabileceğimizi keşfetmeye çalışırız. Tabi geliştirilen ürünün hedef kitlesi de burada önemli bir rol oynar.</p>
<p>Bazı ürünlerin arayüzlerinin son derece basit tasarlanması yeterli iken bazılarında ise tam tersi bir durum söz konusudur.</p>
<p>Hangisi olursa olsun kullanıcı bir insan olarak düşünüldüğünde çok da fazla zorlanmamalı veya kolayca adapte olabilmelidir. Ne kadar kolay kullanılırsa, hedef kitle içerisinde o kadar fazla sayıda farklı profile de ulaşılabilinir. Ancak bazı hallerde ürünün hedef kitlesi o kadar dağınıktır ki, hepsini çekebilmek ya da bir başka deyişle kazanabilmek için yapılan genişletmeler yeterli gelmeyebilir. Böyle bir durumda çevreye şu mesajı vermeniz gerekebilir;</p>
<blockquote>
<p>Ey ahali…Bu gördüğünüz, ürünümüzün dışarıya açılmış olan servisi/servisleri/sdk’sı/api’si. Buyrun istediğiniz gibi uyarlayın, kullanın. Sonuçta ürünümüzün yaşamının bir parçası olabileceksiniz <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_195.png" alt="Winking smile" /></p>
</blockquote>
<p>Özellikle <strong>ALM<em>(Application Lifecycle Management)</em></strong> gibi geniş konuların uygulandığı ürünlerin değerlendirildiği firmalar ve kalabalık ekipleri düşünüldüğünde, bu heterojenlik kendini iyiden iyiye hissettir. Dolayısıyla ürünün geliştiriciler açısından ne kadar ve nasıl <strong>genişletilebileceği </strong>önem kazanır.</p>
<blockquote>
<p>Ekipleriniz içindeki profilleri düşünün! Yazılımcılar IDE’ leri, iş analistleri Word dokümanlarını, Müdür’ ler web browser üzerinden erişilebilen raporları, Release Manager’ lar Team Explorer’ ı, Proje Yöneticileri Ms Project’ i, CIO’ lar ise ürünlerinin hangi sprint’ ler de olup ne kadarlık işlerinin kaldığını okuyabildikleri e-postaları, sever. Listeyi uzatmak mümkün <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_195.png" alt="Winking smile" /></p>
</blockquote>
<p>Bu felsefeden baktığımızda bence <strong>Microsoft</strong>’ un <strong>Team Foundation Server</strong> ürünü epey önemli bir noktada yer alıyor. Hatta <strong>Gartner</strong>’ ın <strong>Application Lifecycle Management</strong> konusundaki bi raprunda yer alan <strong>Magic</strong> <strong>Quadrant</strong> grafiği de, bunu doğrular nitelikte. Kabiliyet ve sunulan vizyon açısından <strong>Microsoft</strong> liderler arasında en iyi noktada yer alıyor diyebiliriz <em>(Rapor hakkında detaylı bilgiye <a href="http://www.gartner.com/technology/reprints.do?id=1-1ASCXON&ct=120606&st=sb" target="_blank">bu adresten</a> ulaşabilirsiniz)</em></p>
<p><a href="https://www.buraksenyurt.com/pics/odatatfs_15.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_15" src="/pics/odatatfs_15_thumb.png" alt="odatatfs_15" width="400" height="436" /></a></p>
<h1>Peki <strong>TFS</strong> takımı bunu nasıl başarıyor?</h1>
<p>Bildiğiniz üzere<strong> Team Foundation Server</strong> ailesi içerisinde, <strong>.Net</strong> tabanlı kullanılabilen <strong>Object</strong> <strong>Modeller<em>(Client Object Model, Server Object Model, Build Process Object Model)</em></strong>, yabancı ürünlerin entegre olabilmesini sağlayan <strong>Provider</strong>’ lar <em><strong>(MSSCCI Provider ve Team Explorer Everywhere)</strong></em>, servis bazlı entegrasyon için <strong>XML Web hizmetleri</strong> var. Ayrıca bilindiği üzere <strong>TFS</strong> in <strong>Cloud</strong> tabanlı çalışan bir başka verisyonu daha bulunmakta.</p>
<h1>Cloud Tabanlı TFS</h1>
<p><strong>Team</strong> <strong>Foundation</strong> <strong>Server</strong> bilindiği üzere bir süredir <strong>Cloud Service</strong> olarak da hizmet vermekte. <strong>5 Windows Live ID</strong> hesabına kadar ücretsiz kullanılabilen hizmet, sunucu modelli kurulum sonucu yapılabilen hemen herşeyi karşılamakta. <strong>Scrum, MSF, CMMI</strong> gibi şablonları doğrudan destekleyen servis, <strong>TFS Web Access</strong> arayüzü ile de oldukça kolay bir kullanıma sahip. <strong>Visual Studio</strong> ailesine, <strong>Excel</strong> gibi ofis ürünlerine kolayca bağlanabilmekte. Hatta son zamanlarda <strong>Git</strong> ile olan entegrasyonu sayesinde, <strong>Git</strong> fanatiği geliştiricilerin de dikkatini çekmeyi başardı.</p>
<p>Bir bulut servisi olduğu için, <strong>TFS</strong> ortamının kurulumunu düşünmemize gerek yok. Sadece abone oluyor veya lisanslı kullanıcı iseniz kira bedelini ödüyorsunuz. Kurulumu düşünmüyor olmanız beraberinde <strong>ölçeklenebilirlik<em>(Scalability)</em>,</strong> sunucu performansı, donanım alımı, personel istihdamı gibi mevzuları da düşünmemize gerek olmadığı anlamına gelmekte.</p>
<blockquote>
<p>Pek tabi bazı kurumlar halen daha bulut servislerine temkinli yaklaşmakta ve hatta doğrudan geri çevirmekte. Örneğin ülkemizdeki BDDK gibi kurumlar, bankaların bu tip bulut tabanlı yapılar ile çalışmalarını ve bilgi alışverişinde bulunmalarını epeyce sorgulamakta ve kolay kolay izin vermemekte.</p>
<p>Açıkçası askeri ve stratejik açıdan düşünürsek ülke ekonomisine ait değerli bilgilerin 3ncü parti sunucularda, ülke dışında tutmak çok da doğru değil bana kalırsa.</p>
</blockquote>
<p><a href="http://tfs.visualstudio.com">http://tfs.visualstudio.com</a> adresinden ulaşılabilen hizmete son aylarda eklenen ve halen geliştirilme aşamasında olan önemli bir yenilikte <strong>OData<em>(Open Data Protocol)</em></strong><em> </em>servis desteği. <strong>XML<em>(eXtensible Markup Language)</em></strong> üzerine oturan ve <strong>URL</strong> bazlı sorgulama yetenekleri tanıyan bu protokol, bir dünya standardı. Standardın hedefi ise veri odaklı yayınlayıcılar<strong><em>(Publishers)</em></strong>.</p>
<p>Hal böyle olunca herhangibir veri kaynağının, özellikle internet ortamı üzerinden <strong>OData</strong> protokolüne göre sorgulanabilmesi mümkün hale geliyor. Bunun tam karşılığı ise, platform bağımsızlıktan başka bir şey değil. Ama bu son derece önemli bir yetenek. Nitekim bulut üzerinde koşan <strong>TFS</strong> hizmetini kullanabilecek istemcileri her hangi bir platform için geliştirebileceğimiz anlamına gelmekte.</p>
<p><a href="http://www.odata.org/" target="_blank">OData</a> protokolünün ön gördüğü veri odaklı sorgular bilindiği üzere tamamen <strong>URL</strong> bazlı olarak çalışmakta. Bu nedenle bulut <strong>TFS</strong> servisi üzerinde duran bilgileri basit bir tarayıcı uygulamayı kullanarak sorgulayabilirsiniz de. Bunun sonucu olarak dilerseniz <strong>TFS</strong> projenizin bazı raporlarını veya yönetsel arabirimi özelliklerini, örneğin mobil cihazınıza kadar indirebilirsiniz. <em>(Bu konu ile ilişkili olarak </em><a href="http://blogs.msdn.com/b/nishasingh/archive/2013/01/08/tfs-dashboard-a-sample-windows-8-store-app-for-team-foundation-server.aspx" target="_blank"><em>Nisha Singh’ in Windows 8 uygulamasına</em></a><em> bir göz atmanızı öneririm)</em></p>
<p>Gelelim bu yazımızdaki konumuza. Hiç kod yazmayacak ve geliştirme yapmayacağız aslında <img class="wlEmoticon wlEmoticon-disappointedsmile" style="border-style: none;" src="/pics/wlEmoticon-disappointedsmile_5.png" alt="Disappointed smile" /> Bir tarayıcı uygulama,<strong> tfs.visualstudio.com</strong> üzerindeki hesabımız ve <strong>OData</strong> servislerinden yararlanarak sorgulamalar gerçekleştireceğiz.</p>
<h1>Seddulbahir</h1>
<p>Bu amaçla ben <strong>seddulbahir.visualstudio.com</strong> adresinde konuşlandırılmış olan ve sahibi olduğum <strong>Team Project Collection </strong>alanını kullanıyor olacağım. <strong>OData</strong> örnekleri için çok basit olarak <strong>SoniK</strong> isimli uydurmasyon bir <strong>Team</strong> <strong>Project</strong> oluşturdum. Söz konusu proje<strong> Scrum 2.2</strong> şablonuna göre kullanılmakta. Şimdilik tek üyesi benim ve tüm <strong>Task</strong>’ lar üzerimde <img class="wlEmoticon wlEmoticon-confusedsmile" style="border-style: none;" src="/pics/wlEmoticon-confusedsmile_30.png" alt="Confused smile" /></p>
<blockquote>
<p>tfs.visualstudio.com servisinin en güzel yanlarından birisi de, son güncellemeleri haberiniz olmasa dahi hızla ve ilk elden implemente ediyor oluşu. Söz gelimi Scrum’ ın yeni bir versiyonunun çıktığını fark etmemiş olabilirsiniz. Ama bulut üzerinde bu güncelleme çıktığı gibi entegre edilmiştir de.</p>
</blockquote>
<p>Tabi <strong>OData</strong> servisleri ile bir <strong>Team Project’</strong> in sorgulanması denince dikkatler hemen <strong>Work Item </strong>içeriklerine çevrilecektir. Yani <strong>Product Backlog Item</strong>, <strong>Task</strong>, <strong>Test</strong> <strong>Case</strong>, <strong>Bug</strong>, <strong>Impediment</strong> gibi öğelere<em>(Scrum için söz konusu olan bu Work Item çeşitleri, seçilen süreç şablonuna göre elbetteki değişiklik gösterebilir) </em>Bu nedenle <strong>SoniK</strong> isimli proje içerisine aşağıdaki ekran görüntüsünde yer alan bazı <strong>Work Item’</strong> ları ekledim ve bunları şimdilik, 2 haftalık süreye sahip olan <strong>Sprint 1</strong> içerisinde değerlendirmeye aldım. Görüldüğü gibi <strong>TO DO</strong>’ dan <strong>IN PROGRESS</strong>’e aldığım iki <strong>Task</strong>’ ım var <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_95.png" alt="Smile" /></p>
<p><a href="https://www.buraksenyurt.com/pics/odatatfs_2.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_2" src="/pics/odatatfs_2_thumb.png" alt="odatatfs_2" width="640" height="415" /></a></p>
<p><a href="https://www.buraksenyurt.com/pics/odatatfs_4.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_4" src="/pics/odatatfs_4_thumb.png" alt="odatatfs_4" width="640" height="311" /></a></p>
<p>Sorgulama işlemine başlamadan önce yapılması gereken küçük bir hazırlık daha var. <strong>OData </strong>servislerini etkinleştirmek için <strong>TFS</strong> hesabımızın profil özelliklerinden<strong> Enable Aternate Credentials</strong> seçeneğini aktif hale getirmemiz ve bir kullanıcı adı ile şifre belirlememiz gerekiyor.</p>
<p><a href="https://www.buraksenyurt.com/pics/odatatfs_1.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_1" src="/pics/odatatfs_1_thumb.png" alt="odatatfs_1" width="599" height="499" /></a></p>
<p>Bu işlemin ardından <a href="https://tfsodata.visualstudio.com/defaultcollection">https://tfsodata.visualstudio.com/defaultcollection</a> adresine girerek başlama vuruşunu yapabiliriz <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_95.png" alt="Smile" /> <strong>domainAdı\kullanıcıAdı </strong>ve <strong>şifre </strong>ile giriş yapabiliriz. Örneğin benim <strong>TFS</strong> projem <strong>seddulbahir.visualstudio.com</strong> olduğundan, <strong>seddulbahir\AlternatifKullanıcıAdı </strong>ve <strong>şifre </strong>ile giriş yapmam gerekiyor. <strong>defaultcollection</strong> adresini sorguladığımızda standart bir <strong>OData</strong> servisinden beklediğimiz sonuçlar ile karşılaşırız. Bize <strong>TFS</strong> hizmeti için sorgulanabilir olan <strong>Entity</strong> adlarının adreslerini içeren bir sayfa üretilecektir. Aşağıdaki ekran görüntüsündeki gibi.</p>
<p><a href="https://www.buraksenyurt.com/pics/odatatfs_3.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_3" src="/pics/odatatfs_3_thumb.png" alt="odatatfs_3" width="595" height="667" /></a></p>
<p>Dikkat edileceği üzere kullanıcılardan <strong>Area</strong>’ lara, <strong>Work Item</strong>’ lardan, <strong>Team Project Collection </strong>içerisindeki <strong>Team Project</strong>' lere, <strong>Build </strong>tanımlamalarından, <strong>Iteration</strong>’ lara kadar sorgulanabilecek oldukça geniş bir yelpaze söz konusudur. Şimdi dilerseniz örnek projemiz için bir kaç <strong>OData </strong>sorgusu icra edelim ve sonuçları görmeye çalışalım.</p>
<h1>Örnek Sorgular</h1>
<p>Aşağıdaki tabloda sorguya ait <strong>URL</strong> ifadeleri, bazı kısa açıklamalar ve <strong>SoniK</strong> için üretilen sonuçlara ait ekran görüntüleri yer almaktadır.</p>
<table style="width: 640px;" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td valign="top" width="640"><strong>Team Project Collection içerisinde yer alan Team Project öğelerinin çekilmesi</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects</td>
</tr>
<tr>
<td valign="top" width="640">Yukarıdaki sorgu hesabımıza ait Team Project Collection içerisinde ne kadar Team project var ise döndürür. Dikkat çekici <strong>entry</strong> özelliklerinden birisi, belirli bir projeye erişebilmek için <strong>id</strong> elementi ile gelen <strong>URL</strong> değeridir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_5.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_5" src="/pics/odatatfs_5_thumb.png" alt="odatatfs_5" width="605" height="661" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Belirli bir Team Project içerisinde tanımlanmış olan Area bilgilerinin çekilmesi</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects('Sonik')/AreaPaths</td>
</tr>
<tr>
<td valign="top" width="640">Bir proje içerisinde pek çok <strong>Area</strong> tanımlanmış olabilir. Genellikle aynı projede birden fazla takımın kendilerine ait <strong>Area</strong>’ lar üzerinde yetkilendirilerek çalışması gibi ihtiyaçlarda ideal bir çözümdür. Sorguda önce Projects üzerinden SoniK’ e gidilmiş ve <strong>AreaPaths</strong> alt entity içeriği talep edilmiştir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_6.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_6" src="/pics/odatatfs_6_thumb.png" alt="odatatfs_6" width="589" height="492" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Bir Area’ nın altında yer alan alt Area’ ların çekilmesi</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/AreaPaths('SoniK%3CDevelopment')/SubAreas</td>
</tr>
<tr>
<td valign="top" width="640">Bazı durumlarda bir <strong>Area</strong> altında birden fazla <strong>Child</strong> <strong>Area</strong> açılmış olabilir. Hatta bu, bir kaç seviyelendirme şeklinde yapılmış da olabilir. Örnek projede aşağıdaki gibi bir <strong>Area</strong> yapısı söz konusudur ve yukardaki <strong>OData</strong> sorgusu ile bu içerik <strong>XML </strong>formatında elde edilebilir. <br /><a href="https://www.buraksenyurt.com/pics/odatatfs_7.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_7" src="/pics/odatatfs_7_thumb.png" alt="odatatfs_7" width="427" height="443" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_8.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_8" src="/pics/odatatfs_8_thumb.png" alt="odatatfs_8" width="515" height="215" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Bir Team Project için söz konusu olan Work Item Öğelerinin toplam sayısını bulmak</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects('Sonik')/WorkItems/$count</td>
</tr>
<tr>
<td valign="top" width="640">Örneğin <strong>Sonik</strong> isimli <strong>Team</strong> <strong>Project</strong> içerisinde yer alan toplam <strong>work</strong> <strong>item</strong> sayısını <strong>count OData</strong> fonksiyonundan yararlanarak bulabiliriz.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_9.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_9" src="/pics/odatatfs_9_thumb.png" alt="odatatfs_9" width="405" height="126" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Belirli bir Id değerine sahip Work Item’ ın elde edilmesi</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects('Sonik')/WorkItems(3)</td>
</tr>
<tr>
<td valign="top" width="640">Bu sorgu ile <strong>3 numaralı ID değerine sahip Work</strong> <strong>Item</strong> bilgisi elde edilmektedir. Tabi çok fazla özellik olduğundan element sayısı da epeyce fazladır. Azaltmak için bir sonraki örnekte olduğu gibi <strong>projection</strong> <strong>type</strong> kullanımı tercih edilebilir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_10.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_10" src="/pics/odatatfs_10_thumb.png" alt="odatatfs_10" width="592" height="788" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Work Item’ lardan ilk 2sinin sadece Title ve Type bilgilerini çekmek</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects('Sonik')/WorkItems?$select=Title,Type&$top=2</td>
</tr>
<tr>
<td valign="top" width="640">Burada aslında bir <strong>projection</strong> kullanımı söz konusudur. <strong>select</strong> anahtar kelimesini takiben, çekilmek istenen özelliklerin adları verilmiştir. <strong>top</strong> anahtar kelimesi ile de kaç tane element çekileceği ifade edilir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_11.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_11" src="/pics/odatatfs_11_thumb.png" alt="odatatfs_11" width="573" height="627" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Sorgu çıktısını JSON(JavaScript Object Notation) formatında elde etmek</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/Projects('Sonik')/WorkItems?$select=Title,Type&$top=3&$format=json</td>
</tr>
<tr>
<td valign="top" width="640">Çıktının sadece <strong>XML</strong> formatında elde edilmesi şart değildir. Örneğin daha az yer tutan <strong>JSON</strong> tipinde bir çıktı üretilmesi için <strong>format</strong> anahtar kelimesinden yararlanılabilir. Yukarıdaki sorguda <strong>Sonik</strong> projesindeki ilk 3 Work Item’ ın <strong>Title</strong> ve <strong>Type</strong> değerlerini içeren <strong>JSON</strong> çıktısı talep edilmektedir. Sonuç aşağıdaki gibidir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_12.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_12" src="/pics/odatatfs_12_thumb.png" alt="odatatfs_12" width="584" height="374" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Bir projedeki belirli bir Work Item tipine ait öğeleri çekmek</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/WorkItems?$filter=Project eq 'Sonik' and Type eq 'Test Case'&$select=Project,Type,Title,AreaPath</td>
</tr>
<tr>
<td valign="top" width="640">Örnek sorguda <strong>filter</strong> ve <strong>select</strong> anahtar kelimelerinden yararlanılmış olup, <strong>Sonik</strong> isimli projede yer alan <strong>Test</strong> <strong>Case</strong> tipindeki <strong>Work Item</strong>’ ların <strong>Project</strong>, <strong>Type</strong>, <strong>Title </strong>ve <strong>AreaPath </strong>bilgileri talep edilmiştir.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_13.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_13" src="/pics/odatatfs_13_thumb.png" alt="odatatfs_13" width="584" height="435" /></a></td>
</tr>
<tr>
<td valign="top" width="640"><strong>Belirli bir Sprint içindeki Work Item bilgilerinin çekilmesi</strong></td>
</tr>
<tr>
<td valign="top" width="640">https://tfsodata.visualstudio.com/DefaultCollection/WorkItems?$filter=Project eq 'Sonik' and Type eq 'Product Backlog Item' and IterationPath eq 'SoniK\Release 1\Sprint 1'&$select=Project,Type,Title,AreaPath,IterationPath</td>
</tr>
<tr>
<td valign="top" width="640">Örnekte <strong>Sprint 1</strong> içerisine alınmış olan <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> öğelerinin <strong>Project</strong>, <strong>Type</strong>, <strong>Title</strong>, <strong>AreaPath</strong>, <strong>IterationPath</strong> değerleri sorgulanmaktadır. <strong>filter</strong> anahtar kelimesi ile birden fazla kriterin hesaba katılması noktasında <strong>and</strong> ve <strong>or</strong> operatörlerinden yararlanılır.</td>
</tr>
<tr>
<td valign="top" width="640"><a href="https://www.buraksenyurt.com/pics/odatatfs_14.png"><img style="margin: 4px 0px; display: inline;" title="odatatfs_14" src="/pics/odatatfs_14_thumb.png" alt="odatatfs_14" width="551" height="784" /></a></td>
</tr>
</tbody>
</table>
<p><br />Şu an için <strong>TFS</strong> <strong>Odata</strong> servis sorgularında <strong>filter</strong>, <strong>count</strong>, <strong>select</strong>, <strong>orderby</strong>, <strong>top</strong>, <strong>skip</strong>, <strong>format</strong> ve <strong>callback</strong> anahtar kelimeleri kullanılabilmektedir. Ancak bu anahtar kelime seti artabilir. Sorgular sırasında <strong>?</strong> ve <strong>$</strong> harflerine de dikkat edilmelidir. Tüm <strong>OData</strong> komutlarının önünde dikkat edileceği üzere <strong>$</strong> harfi yer almaktadır. Her ne kadar örneklerde ağırlıklı olarak <strong>Work Item</strong>’ lar üzerinde durulmuş olsa da <strong>DefaultCollection</strong> altında sunulan <strong>Entity</strong>’ lerin çoğu üzerinde sorgulamalar yapılabilir. Bunu denemenizi öneririm <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_195.png" alt="Winking smile" /></p>
<p>Görüldüğü üzere söz konusu <strong>OData</strong> sorgularını kullanarak farklı platformlar üzerinde çalışacak istemci uygulamaların geliştirilmesinin önü son derece açıktır. Şu anda halen geliştirilmekte olan <a href="https://tfsodata.visualstudio.com/" target="_blank">TFS OData servislerinin kullanımına ilişkin detaylı bilgileri bu adresten takip edebilirsiniz</a>. Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><span style="color: #ff0000;">[Orjinal Yazım Tarihi 3/20/2013]</span></p>2013-08-25T10:35:00+00:00tfsteam foundation servertfs 2012odataodata servicesopen data protocolxmlhttp gettfs.visualstudio.comfiltercountselectorderbytopskipformatjsonjava script object notationcallbackdefault collectionteam projectteam project collectionbsenyurtÖzellikle ALM(Application Lifecycle Management) gibi geniş konuların uygulandığı ürünlerin değerlendirildiği firmalar ve kalabalık ekipleri düşünüldüğünde, bu heterojenlik kendini iyiden iyiye hissettir. Dolayısıyla ürünün geliştiriciler açısından ne kadar ve nasıl genişletilebileceği önem kazanır...https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=51cbef01-43ae-430b-8b4f-ccfc0ce0d6061https://www.buraksenyurt.com/trackback.axd?id=51cbef01-43ae-430b-8b4f-ccfc0ce0d606https://www.buraksenyurt.com/post/TFS-OData-Destegi#commenthttps://www.buraksenyurt.com/syndication.axd?post=51cbef01-43ae-430b-8b4f-ccfc0ce0d606https://www.buraksenyurt.com/post/Java-ile-TFS-Client-Object-Model-KonusuyorEclipse Üzerinden Java ile TFS Client Object Model Konuşuyor2013-05-12T10:10:00+00:00bsenyurt<p><a href="https://www.buraksenyurt.com/pics/developers.jpg"><img style="margin: 4px 0px; display: inline; float: right;" title="developers" src="/pics/developers_thumb.jpg" alt="developers" width="200" height="298" align="right" /></a>Merhaba Arkadaşlar,</p>
<p>Çok değil daha bir kaç sene öncesine kadar<em>(Özellikle .Net’ in duyurulduğu yıllarda ve izleyen bir kaç senede) </em>yazılım dünyasında neredeyse yandaki resimdekine benzer bir kavga vardı<em>(Benzetmeyi biraz abartmış olabilirim)</em> </p>
<p><strong>Java</strong>’ cılar, <strong>C#</strong>’ çıları pek sevmez iken tam tersi durum da pekala geçerliydi. Ben hiç bir zaman birisinin fanatiği olmadım. Hatta Java ile ufak çaplı bir kaç deneyimim bile oldu.</p>
<p>Peki gerçek dünya böyle mi? Özellikle kalabalık yazılım ekiplerinin olduğu, çok fazla sayıda ürünün koştuğu dünyalarda, sadece <strong>Java</strong>’ cıları, <strong>C#</strong>’ çıları değil, daha pek çok programlama dili geliştiricilerini bir arada görmekteyiz. Öneğin ben bulunduğum konum itibariyle <strong>C</strong>’ cilerin, <strong>Assembler</strong>’ cıların, <strong>PowerBuilder</strong>’ cıların, <strong>.Net</strong>’ çilerin, <strong>Java</strong>’ cıların ve hatta <strong>Cobol</strong>’ cuların arasında yaşamaktayım.</p>
<p>Hepsi kendi dünyalarını kullanarak ürünler geliştiriyor olsalar da, zaman içerisinde birbirleriyle konuşması gereken uygulamalar bütününün de bir parçası olmaktan kaçamıyorlar. Özellikle işin içerisine bir <strong>ALM<em>(Application LifeCycle Management)</em></strong> aracı girdiğinde. İşte bu günkü konumuzda buna itaf edilecek <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /> Haydi gelin başlayalım.</p>
<p>Bildiğiniz üzere bir süredir <strong>Team Foundation Server’</strong> ın çevre dünya ile olan etkileşimini incelemeye çalışıyorum. Açıkçası <strong>TFS’</strong> in gerek servis yapısı gerek<strong> Client Object Model</strong> gibi kütüphaneleri sayesinde, dış dünya ile olan entegrasyonu son derece kolay. Bu gün buna bir kere daha inandım. Çünkü bir <strong>Java</strong> uygulaması içerisinde <strong>TFS Client Object Model</strong>’ i kullanarak, bir <strong>Team Project</strong>’ in <strong>Work</strong> <strong>Item</strong> listesini sorguladım <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /> Nasıl yaptığımı merak ediyorsanız okumaya devam edin. Tabi bu işte de çok önemli bir yardımcım vardı. O da <strong>Microsoft </strong>tarafından geliştirilen ve ücretsiz olarak sunulan <strong>Client Object Model SDK</strong>’sı. Ama <strong>Java</strong> için olan sürümü.</p>
<blockquote>
<p><strong>Microsoft Team Foundation Server 2012 Software Development Kit for Java</strong> içeriğini <a href="http://www.microsoft.com/en-us/download/details.aspx?id=22616" target="_blank">bu adresten</a> indirebilirsiniz<em>(Makaleyi hazırladığım tarih itibariyle 15 Şubat 2013’ te yayınlanmış güncel bir sürümü bulunmaktaydı)</em></p>
</blockquote>
<h1>Senaryo</h1>
<p>Senaryomuz esas itibariyle yine bir <strong>Hello World</strong> uygulaması olacak. <img class="wlEmoticon wlEmoticon-embarrassedsmile" style="border-style: none;" src="/pics/wlEmoticon-embarrassedsmile_5.png" alt="Embarrassed smile" /> <strong>Console</strong> ekranına belirli bir <strong>Team Project</strong> içerisinde yer alan <strong>Work</strong> <strong>Item</strong> bilgilerini<em>(Product Backlog Item, Bug, Task gibi)</em> yazdırmaya çalışacağız. Örneğin <strong>Work Item</strong>’ ın başlığını<em>(Title)</em>, tipini<em>(WorkItem Type)</em>, numarasını<em>(ID)</em> düzgün bir sırada çekmeyi deneyebiliriz. Java kodlaması yapacağımız için <strong>Eclipse</strong> gibi bir <strong>IDE</strong> tercih edilebilir ki ben öyle yaptım <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /></p>
<h1>Bebek Adımları</h1>
<h2>Adım 0</h2>
<p>İlk olarak <strong>Eclipse</strong> üzerinde yeni bir <strong>Java</strong> <strong>Projesi</strong> oluşturarak işe başlayalım<em>(File->New->Java Project)</em>. Ben <strong>UsingClientObjectModel</strong> olarak adlandırdığım projeyi, sistemimde kurulu olan <strong>Workspace</strong> içerisinde oluşturdum. <strong>Runtime</strong> olarak <strong>1.6</strong> sürümünü kullanmayı tercih ediyorum. Bu nedenle daha önceki projelerden varsayılan olarak kalan <strong>Use an execution environment JRE</strong> değerini olduğu gibi bıraktım.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_1.png"><img style="margin: 4px 0px; display: inline;" title="jtfs_1" src="/pics/jtfs_1_thumb.png" alt="jtfs_1" width="500" height="658" /></a></p>
<p>Bu üretim işlemi sonrasında <strong>Eclipse IDE</strong>’ sinde aşağıdakine benzer bir içerik oluştuğunu görmeliyiz. <em>(Elbette sisteminizde <strong>Java Runtime Environement’</strong> in yüklü olduğu fiziki adresler daha farklı olabilir.)</em></p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_2.png"><img style="display: inline;" title="jtfs_2" src="/pics/jtfs_2_thumb.png" alt="jtfs_2" width="376" height="329" /></a></p>
<h2>Adım 1</h2>
<p>İkinci adım ise main metodunu içerecek olan ve asıl kodlarımızı yazacağımız sınıfı eklemek olacaktır. <strong>Visual Studio</strong> tarafından kalma bir alışkanlık nedeniyle <strong>Program</strong> olarak isimlendirdiğim sınıf, <strong>tfs.clientobjectmodel.application</strong> isimli paket içerisinde konuşlandırılacak<em>(Siz kendi istediğiniz paket tanımlamasını yapabilirsiniz)</em> Krtik noktalardan birisi de, <strong>public static void main(String[] args)</strong> seçeneğinin işaretli olmasıdır. Bu, tahmin edeceğiniz üzere programın giriş noktası olan <strong>main</strong> metodudur.</p>
<blockquote>
<p>C# tarafından da bildiğiniz üzere static Main metodu, exe tipindeki uygulamaların giriş noktasıdır. Aynı durum Java uygulamaları için de geçerlidir. Tek fark Java tarafında isimlendirme standartı gereği küçük m harfi ile başlanmasıdır. Dikkat edileceği üzere her iki dilde metoda parametre olarak string tipinden bir dizi alır. Programa dış ortamdan parametre aktarabilmek amacıyla <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /></p>
</blockquote>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_3.png"><img style="display: inline;" title="jtfs_3" src="/pics/jtfs_3_thumb.png" alt="jtfs_3" width="500" height="598" /></a></p>
<p>Bu işlemin sonucunda <strong>Eclipse IDE</strong>’ si bizim için aşağıdaki ekran görüntüsünde yer alan içeriği üretmelidir.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_4.png"><img style="display: inline;" title="jtfs_4" src="/pics/jtfs_4_thumb.png" alt="jtfs_4" width="624" height="228" /></a></p>
<h2>Adım 2</h2>
<p>Üçüncü adımda, bilgisayarımıza indirip açtığımız <strong>TFS SDK</strong>’ sını referans ediyor olacağız. Bunun için ilgili <strong>JAR</strong> dosyasının uygulamaya bildirilmesi<em>(bir başka deyişle referans edilmesi)</em> gerekmektedir. Söz konusu bildirim için proje özelliklerinden <strong>Java Build Path </strong>kısmına gelmeli ve <strong>Add External JARs</strong> düğmesini kullanarak <strong>com.microsoft.tfs.sdk-11.0.0</strong> isimli <strong>JAR</strong> dosyasını seçmeliyiz.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_5.png"><img style="display: inline;" title="jtfs_5" src="/pics/jtfs_5_thumb.png" alt="jtfs_5" width="603" height="537" /></a></p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_6.png"><img style="display: inline;" title="jtfs_6" src="/pics/jtfs_6_thumb.png" alt="jtfs_6" width="406" height="149" /></a></p>
<blockquote>
<p>Konu ile ilişkili olarak yaptığım araştırmalarda şöyle bir kullanıma da rastladım. Hazırlanan Java uygulamasının dağıtılabileceği de düşünülürse SDK’ nın Redistributable olan parçalarının proje klasörü altına kopyalanması ve ilgili path bildirimlerinin bu fiziki adresleri gösterecek şekilde yapılması yolu da tercih edilebilir. Böyle bir durumda Add JARs düğmesinden hareket edilir.</p>
</blockquote>
<p>Sonuç olarak <strong>Java Build Path</strong> kısmının aşağıdaki ekran görüntüsündeki gibi oluşması gerekmektedir.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_7.png"><img style="display: inline;" title="jtfs_7" src="/pics/jtfs_7_thumb.png" alt="jtfs_7" width="603" height="186" /></a></p>
<p>Ne varki bu yeterli değildir. Bir de eklenen <strong>JAR </strong>dosyası için <strong>Native Libary Location </strong>değerinin <strong>set </strong>edilmesi gerekmektedir. Bunun için aşağıdaki ekran görüntüsünde görüldüğü üzere, <strong>SDK</strong>’ nın açılması sonucu oluşan<strong> redist\native</strong> klasörüne kadar inilmeli ve platforma uygun olan klasör seçilmelidir. Ben <strong>x86</strong> işlemcili <strong>win32</strong> tabanlı bir sistem de çalıştığımdan buna uygun olan klasörü seçtim<em>(Native klasörü altında <strong>Linux</strong>, <strong>MacOSX</strong>, <strong>Solaris</strong> gibi pek çok sistem için gerekli kütüphaneler bulunmaktadır)</em></p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_8.png"><img style="display: inline;" title="jtfs_8" src="/pics/jtfs_8_thumb.png" alt="jtfs_8" width="611" height="361" /></a></p>
<p>Buraya kadar ki işlemlerimiz sonrasında <strong>Eclipse IDE</strong>’ sinde projemize ait olan son görünüm de aşağıdaki gibi olacaktır. Dikkat edileceği üzere <strong>TFS SDK</strong>’ sı, <strong>Referenced Libraries</strong> kısmında görülmektedir.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_9.png"><img style="display: inline;" title="jtfs_9" src="/pics/jtfs_9_thumb.png" alt="jtfs_9" width="375" height="274" /></a></p>
<h1>Örnek kodlar</h1>
<p>Şimdi kod tarafını geliştirmeye başlayabiliriz. Aslında <strong>.Net</strong> tarafında <strong>Client Object Model’</strong> in kullanımından çok da farklı bir işlem yapmamıza gerek yoktur. <strong>TFS Client Object Model</strong>’ in nesne yapısının hemen hemen aynısı burada da inşa edilmiştir. Şimdi Program sınıfına ait kodlarımızı aşağıdaki gibi geliştirelim.</p>
<p>package tfs.clientobjectmodel.application;</p>
<pre class="brush:java;auto-links:false;toolbar:false" contenteditable="false">import java.net.URI;
import java.net.URISyntaxException;
import com.microsoft.tfs.core.TFSTeamProjectCollection;
import com.microsoft.tfs.core.clients.workitem.WorkItem;
import com.microsoft.tfs.core.clients.workitem.WorkItemClient;
import com.microsoft.tfs.core.clients.workitem.query.WorkItemCollection;
import com.microsoft.tfs.core.httpclient.Credentials;
import com.microsoft.tfs.core.httpclient.HttpException;
public class Program {
public static void main(String[] args)
throws HttpException, URISyntaxException {
System.setProperty("com.microsoft.tfs.jni.native.base-directory"
, "C:\\Program Files\\TFS-SDK-11.0.0.1302\\TFS-SDK-11.0.0\\redist\\native");
URI uri=new URI("http://tfsserver:8080/tfs/defaultcollection");
Credentials user=new com.microsoft.tfs.core.httpclient.DefaultNTCredentials();
TFSTeamProjectCollection collection=new TFSTeamProjectCollection(uri,user);
WorkItemClient wiClient=collection.getWorkItemClient();
WorkItemCollection workItems=wiClient
.query("Select ID,Title from WorkItems " +
"where ([Team Project]='ARGE') order by [Work Item Type]");
System.out.println("Active statusunde olan toplam "+
workItems.size()+" work item bulunmustur");
for(int i=0;i<workItems.size();i++)
{
WorkItem workItem=workItems.getWorkItem(i);
System.out.println(workItem.getTitle()
+" "+workItem.getType().getName()
+" "+workItem.getID()
+" "+workItem.getProject().getName()
);
}
}
}</pre>
<p>İlk dikkat edilmesi gereken nokta <strong>System</strong> özelliklerine bir <strong>key-value</strong> eklenmiş olmasıdır. <strong>com.microsoft.tfs.jni.native.base-directory</strong> isimli <strong>key</strong> için <strong>C:\\Program Files\\TFS-SDK-11.0.0.1302\\TFS-SDK-11.0.0\\redist\\native</strong> adresi <strong>value</strong> olarak verilmiştir. Normal şartlarda bu bildirim komut satırından <strong>java.exe</strong> uygulaması kullanılarak da yapılabilir. Söz konusu sistem özelliğinin <span style="text-decoration: underline;">bir kere set edilmesi</span> yeterlidir. Bu bildirim ile aslında <strong>native loader</strong>’ ın sisteme tanıtılması işlemi gerçekleştirilir. Eğer ilgili bildirim yapılmazsa, çalışma zamanında aşağıdaki hata mesajı ile karşılaşılması muhtemeldir.</p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">Exception in thread "main" java.lang.UnsatisfiedLinkError: com.microsoft.tfs.jni.internal.platformmisc.NativePlatformMisc.nativeGetEnvironmentVariable (Ljava/lang/String;)Ljava/lang/String;
at com.microsoft.tfs.jni.internal.platformmisc.NativePlatformMisc.nativeGetEnvironmentVariable (Native Method)
at com.microsoft.tfs.jni.internal.platformmisc.NativePlatformMisc.getEnvironmentVariable (NativePlatformMisc.java:134)
at com.microsoft.tfs.jni.PlatformMiscUtils.getEnvironmentVariable (PlatformMiscUtils.java:52)
at com.microsoft.tfs.core.config.httpclient.DefaultHTTPClientFactory.shouldAcceptUntrustedCertificates (DefaultHTTPClientFactory.java:288)
at com.microsoft.tfs.core.config.httpclient.DefaultHTTPClientFactory.configureClientParams (DefaultHTTPClientFactory.java:324)
at com.microsoft.tfs.core.config.httpclient.DefaultHTTPClientFactory.newHTTPClient (DefaultHTTPClientFactory.java:137)
at com.microsoft.tfs.core.TFSConnection.getHTTPClient (TFSConnection.java:1041)
at com.microsoft.tfs.core.TFSConnection.getWebService (TFSConnection.java:874)
at com.microsoft.tfs.core.config.client.DefaultClientFactory$9.newClient (DefaultClientFactory.java:265)
at com.microsoft.tfs.core.config.client.DefaultClientFactory.newClient (DefaultClientFactory.java:90)
at com.microsoft.tfs.core.TFSConnection.getClient (TFSConnection.java:1470)
at com.microsoft.tfs.core.TFSTeamProjectCollection.getWorkItemClient (TFSTeamProjectCollection.java:370)
at tfs.clientobjectmodel.application.Program.main (Program.java:26)</pre>
<p>Bundan sonraki kısımda ilk olarak <strong>TFSTeamProjectCollection</strong> tipinden bir nesne örneklendiği görülmektedir. Örnekleme sırasında ilk parametre olarak <strong>DefaultCollection’</strong> a ait <strong>url</strong> adresi verilmiştir<em>(Programda TFS sunucusunun kurulu olduğu makinedeki varsayılan <strong>Team Project Collection </strong>kullanılmaktadır)</em>. <strong>URI</strong> sınıfından yapılan bu bildirimi <strong>Credentials</strong> tipinden bir parametre takip etmektedir. Makineyi açan kullanıcının <strong>Credential</strong> bilgisi ile <strong>TFS</strong>’ e bağlanılmak istendiğinden <strong>DefaultNTCredentials</strong> tipinden bir nesne örneği ele alınmıştır. Ancak bir kullanıcı adı ve şifre ile gidilmek istenirse, <strong>UsernamePasswordCredentials</strong> sınıfından da yararlanılabilir<em>(Elbette ilgili kullanıcıların söz konusu TFS sunucusuna ve koleksiyona erişebildiğini, bir başka deyişle gerekli yetkilere sahip olduğunu var sayıyoruz)</em></p>
<p>Kod parçasında <strong>ARGE</strong> isimli projeye ait <strong>Work Item</strong>’ lar çekilmeye çalışılmaktadır. Bu sebepten <strong>WorkItemStore</strong> servisine erişilmesi gerekmektedir. İlgili servisi kullanabilmek için <strong>getWorkItemClient</strong> fonksiyonu çağırılmaktadır. Bu metod geriye <strong>WorkItemClient</strong> tipinden bir referans döndürmektedir. Bu referans üzerinden çağırılan <strong>query</strong> fonksiyonuna girilen <strong>WIQL<em>(WorkItem Query Language)</em></strong> sorgusu ile de <strong>WorkItemCollection</strong> elde edilir. Bu koleksiyon sorguya uygun bir <strong>Work</strong> <strong>Item</strong> içeriğini taşıyacaktır.</p>
<p>Pek tabi <strong>Java</strong> tarafında, <strong>.Net</strong>’ te olduğu gibi <strong>Property </strong>isimli bir tip üyesi<em>(Type Member)</em> bulunmamaktadır. Ancak <strong>.Net</strong>’ ten aşina olduğumuz <strong>WorkItem</strong> özelliklerine <strong>get</strong> ön ekli metodlar yardımıyla ulaşabiliriz. Örnekte <strong>Work Item</strong>’ ın <strong>Title</strong> değeri için <strong>getTitle()</strong>, Work Item tipinin adı için <strong>getType().getName()</strong>, sistem de kayıtlı olan <strong>ID </strong>bilgisi için de <strong>getID() </strong>metodu kullanılmıştır.</p>
<p>Sonuç olarak <strong>ARGE</strong> isimli projedeki <strong>Work Item</strong>’ ların <strong>ID,Title </strong>değerlerinin, <strong>Work Item </strong>tipine göre sıralanarak elde edilmesi işlemi icra edilmektedir. Uygulamanın çalışma zamanı sonuçları aşağıda görüldüğü gibidir<em>(Farklı WIQL sorguları ile örneği zenginleştirmeyi denemenizi öneririm <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /> )</em></p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_10.png"><img style="margin: 4px 0px; display: inline;" title="jtfs_10" src="/pics/jtfs_10_thumb.png" alt="jtfs_10" width="637" height="686" /></a></p>
<p>Senaryoyu işlettiğim sistemde test amaçlı olarak kullandığım <strong>ARGE</strong> isimli <strong>Team Project</strong>, <strong>Scrum 2.0</strong> şablonunu kullanmaktaydı. Bu nedenle <strong>Product Backlog Item, Task </strong>ve <strong>Bug </strong>gibi <strong>Work Item </strong>öğelerini barındırmaktadır.</p>
<h1>Biraz Daha</h1>
<p>Dilerseniz örnek kod parçasını biraz daha geliştirmeye çalışalım. Örneğin yeni bir <strong>Work</strong> <strong>Item</strong> nasıl eklenir ona bakalım. <strong>.Net</strong> tarafından biraz farklı olarak yeni bir <strong>WorkItem</strong> nesnesinin örneklenmesi için <strong>Project</strong> sınıfı üzerinden <strong>WorkItemClient</strong> referansına ulaşışması ve <strong>newWorkItem</strong> metodunun çağırılması gerekmektedir<em>(Yani <strong>WorkItem</strong> sınıfını doğrudan bir <strong>yapıcı metod-Constructor</strong> ile örnekleyemiyoruz) </em>Aynen aşağıdaki kod parçasında olduğu gibi.</p>
<pre class="brush:java;auto-links:false;toolbar:false" contenteditable="false">package tfs.clientobjectmodel.application;
import java.net.URI;
import java.net.URISyntaxException;
import com.microsoft.tfs.core.TFSTeamProjectCollection;
import com.microsoft.tfs.core.clients.workitem.WorkItem;
import com.microsoft.tfs.core.clients.workitem.WorkItemClient;
import com.microsoft.tfs.core.clients.workitem.project.Project;
import com.microsoft.tfs.core.clients.workitem.wittype.WorkItemType;
import com.microsoft.tfs.core.httpclient.Credentials;
import com.microsoft.tfs.core.httpclient.HttpException;
public class Program {
public static void main(String[] args)
throws HttpException, URISyntaxException {
URI uri=new URI("http://tfsserver:8080/tfs/defaultcollection");
Credentials user=new com.microsoft.tfs.core.httpclient.DefaultNTCredentials();
TFSTeamProjectCollection collection=new TFSTeamProjectCollection(uri,user);
WorkItemClient wiClient=collection.getWorkItemClient();
Project argeProject=wiClient.getProjects().get("ARGE");
WorkItemType pbi=argeProject.getWorkItemTypes().get("Product Backlog Item");
WorkItem newWorkItem=argeProject.getWorkItemClient().newWorkItem(pbi);
newWorkItem.setTitle("Backoffice ekranlarin icin wire frame tasarim calismalari");
newWorkItem.save();
System.out.println(newWorkItem.getID()+" numarasi ile bir Product Backlog Item olusturuldu");
}
}</pre>
<p>Dikkat edilmesi gereken noktalardan birisi de <strong>newWorkItem</strong> metoduna parametre olarak üretilmek istenen <strong>work</strong> <strong>item</strong> tipinin verilmesidir. Bu bildirim için <strong>WorkItemType</strong> sınıfına ait bir nesne örneği kullanılmaktadır. <strong>WorkItemType</strong> üretimi için projeye ait nesne örneği üzerinden önce var olan <strong>WorkItem</strong> tiplerinin elde edilmesi işlemi gerçekleştirilmiş, ardından ise <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> tipi çekilmiştir. Bu son derece mantıklıdır, nitekim ilgili projenin şablonu<em>(ki örneğimizde Scrum 2.0 söz konusudur)</em> tarafından kullanılan <strong>Work</strong> <strong>Item</strong> tipleri ne ise, onlara ait <strong>Work</strong> <strong>Item</strong> nesneleri örneklenebilir. Üretilen <strong>Product</strong> <strong>Backclog</strong> <strong>Item</strong> için bir <strong>Title</strong> değeri verilmiş ve sonrasında <strong>Save</strong> metodu kullanılarak kayıt işlemi gerçekleştirilmiştir. Uygulama çalıştırıldığında hem <strong>Console</strong> penceresinden hem de ilgili projeye ait <strong>Backlog</strong>’ da bir öğenin oluşturulduğu gözlemlenecektir.</p>
<p><a href="https://www.buraksenyurt.com/pics/jtfs_11.png"><img style="margin: 4px 0px; display: inline;" title="jtfs_11" src="/pics/jtfs_11_thumb.png" alt="jtfs_11" width="593" height="605" /></a></p>
<p>Görüldüğü üzere <strong>Team Foundation Server Client Object Model</strong>’ in, <strong>Java </strong>tarafında kullanılması da son derece kolaydır. Örnek, tahmin edeceğiniz üzere<strong> Hello World</strong> formatındadır. Ancak daha önceki yazılarımızı baz alarak, .<strong>Net</strong> tarafındaki <strong>Client Object Model </strong>kodlarını, <strong>Java </strong>tarafına taşımayı deneyebilirsiniz. <strong>Kim demiş Java, Microsoft’ u, Microsoft’ ta Java’ yı umursamıyor diye</strong> <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_194.png" alt="Winking smile" /> Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>2013-05-12T10:10:00+00:00javaeclipseteam foundation servertfstfs 2012entegrasyontfs client object modelclient object modelwork itemworkitemstoretfs servicesbsenyurtBildiğiniz üzere bir süredir Team Foundation Server’ ın çevre dünya ile olan etkileşimini incelemeye çalışıyorum. Açıkçası TFS’ in gerek servis yapısı gerek Client Object Model gibi kütüphaneleri sayesinde, dış dünya ile olan entegrasyonu son derece kolay. Bu gün buna bir kere daha inandım. Çünkü bir Java uygulaması içerisinde TFS Client Object Model’ i kullanarak, bir Team Project’ in Work Item listesini sorguladım Winking smile Nasıl yaptığımı merak ediyorsanız okumaya devam edin. Tabi bu işte de çok önemli bir yardımcım vardı. O da Microsoft tarafından geliştirilen ve ücretsiz olarak sunulan Client Object Model SDK’sı. Ama Java için olan sürümü.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=f2307637-9861-4e65-b85b-c2d444f650b53https://www.buraksenyurt.com/trackback.axd?id=f2307637-9861-4e65-b85b-c2d444f650b5https://www.buraksenyurt.com/post/Java-ile-TFS-Client-Object-Model-Konusuyor#commenthttps://www.buraksenyurt.com/syndication.axd?post=f2307637-9861-4e65-b85b-c2d444f650b5https://www.buraksenyurt.com/post/TFS-Client-Object-Model-ile-Word-EntegrasyonuTFS Client Object Model ile Word Entegrasyonu2013-04-11T13:15:00+00:00bsenyurt<p><a href="https://www.buraksenyurt.com/pics/Dodge-Challenger-production-1024x566.jpg"><img style="margin: 4px 0px; display: inline; float: right;" title="Dodge-Challenger-production-1024x566" src="/pics/Dodge-Challenger-production-1024x566_thumb.jpg" alt="Dodge-Challenger-production-1024x566" width="320" height="177" align="right" /></a>Merhaba Arkadaşlar,</p>
<p>Geçtiğimiz gün <strong>National Geographic</strong> kanalında <strong>Mega Fabrikalar’</strong> ı seyretme fırsatı buldum. Amerikalı <strong>Dodge</strong> firması efsane <strong>Challanger</strong>‘ ı yeniden üretmekteydi. Konu bu üretimin gerçekleştirildiği mega fabrikaydı.</p>
<p>Robotların, gelişmiş endüstürinin ve insan gücünün bir araya geldiği fabrika, sadece 24 saat içerisinde üretim hattından mükemmel spor arabalar çıkmaktaydı. Üstelik motor bloğu da kıtanın bir diğer ucundan geliyordu.</p>
<p>Her ne kadar mükemmele yakın bir üretim bandı da olsa, akıllı bilgisayarlar üretim sürecindeki her adımı gözlemliyor ve bir istisna olması halinde bandı durduruyordu. O da yetmiyor pek çok noktada usta insanlar devreye giriyor ve gerekirse üretim bandını kendi insiyatifleri ile durduruyorlardı. Tabi burada yazarak anlatmak çok zor o yüzden mutlaka seyredin derim. Aslında belgeseli izlerken en çok da şunu düşündüm <strong>“Böyle muazzam yapılar nasıl oluyor da inşa ediliyor? İnsan aklı ne kadar muazzam ki her ayrıntıyı düşünüyor, düşünmeye çalışıyor”</strong></p>
<p>Derken bilgisayarımın başına döndüm ve kendi kendime şöyle dedim <strong>“E illa ki bir Hello World uygulamaları vardır yahu” </strong><img class="wlEmoticon wlEmoticon-nerdsmile" style="border-style: none;" src="/pics/wlEmoticon-nerdsmile.png" alt="Nerd smile" /></p>
<p>Bu yazımız ile birlikte <strong>Team Foundation Server </strong>maceralarımıza devam etmeye çalışıyor olacağız. Yeni bölümüzde <strong>Client Object Model</strong>’ i bir <strong>Word</strong> uygulaması içerisinde kullanmaya çalışacağız ve çok basit olarak <strong>Work Item </strong>öğelerini nasıl kayıt edebileceğimizi göreceğiz.</p>
<blockquote>
<p>Team Foundation Server dünyası ile ilişkili önceki yazılarıma aşağıdaki adreslerden ulaşabilirsiniz.</p>
<ul>
<li><a href="https://www.buraksenyurt.com/post/TFS-2012-Client-Object-Model-icin-Hello-World" target="_blank">TFS Client Object Model için Hello World</a></li>
<li><a href="https://www.buraksenyurt.com/post/TFS-Web-Services-ve-Kullanimi" target="_blank">TFS Web Services ve Kullanımları</a></li>
<li><a href="https://www.buraksenyurt.com/post/Heryerden-TFS-Kullanabilmek" target="_blank">Heryerden TFS Kullanabilmek</a></li>
</ul>
</blockquote>
<p>Çalışmakta olduğumuz <strong>Team Project</strong>’ in <strong>süreç şablonu<em>(Process Template)</em> </strong>ne olursa olsun<em><strong>(Scrum, MSF, CMMI)</strong> </em>giriş yapılan öğeler <strong>Work Item</strong> olarak düşünülmektedir. Örneğin <strong>Scrum</strong> felsefesi göz önüne alındığında <strong>Product Backlog Item</strong>, <strong>Task</strong>, <strong>Bug</strong>, <strong>Test</strong> <strong>Case</strong> ve <strong>Impediment</strong> birer <strong>Work Item</strong>’ dır. <strong>CMMI </strong>şablonuna bakıldığında ise <strong>Requirement</strong>, <strong>Task</strong>, <strong>Bug</strong>, <strong>Change</strong> <strong>Request</strong>, <strong>Issue</strong>, <strong>Review</strong>, <strong>Risk</strong> ve <strong>Test</strong> <strong>Case</strong> birer <strong>Work</strong> <strong>Item</strong> olarak düşünülmektedir.</p>
<p>Pek tabi bu <strong>Work Item </strong>öğeleri <strong>Client Object Model</strong> tarafında da birer tip olarak ele alınabilirler. <strong>Client Object Model</strong> bilindiği üzere, <strong>Team Foundation Server</strong> ın dış dünya ile olan iletişiminde ve özellikle çevre araçlar ile olan entegrasyonunda önemli bir yere sahiptir. Dilerseniz örneğimize geçelim ve adım adım ilerleyerek konuyu anlamaya çalışalım.</p>
<h1>Senaryo</h1>
<p>Elimizde <strong>Scrum 2.0</strong> formatında oluşturulmuş bir <strong>Team Project</strong> var. Amacımız <strong>Word</strong> belgesi içerisinden, bir <strong>Product Backlog Item</strong> ve buna bağlı iki <strong>Task</strong> öğesinin kayıt edilmesini sağlamak. Olayı son derece basit bir biçimde ele alacağımızdan <strong>Product Backlog Item</strong> ve <strong>Task</strong> öğeleri için sadece <strong>Title</strong> ve <strong>Description</strong> içeriklerin yer veriyor olacağız. Kritik noktalardan birisi de, <strong>Task</strong> öğeleri ile <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> arasında <strong>Parent-Child</strong> ilişkinin kurulmasıdır. Yani <strong>Task</strong> öğeleri ilgili <strong>Product Backlog</strong>’ a bağlı olacaklardır.</p>
<h1>Ön Hazırlıklar ve Doküman Tasarımı</h1>
<p>İşe ilk olarak <strong>Visual Studio 2012</strong> ortamında bir <strong>Word 2010 Document </strong>projesi oluşturarak başlamalıyız.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_1.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_1" src="/pics/tfsword_1_thumb.png" alt="tfsword_1" width="640" height="360" /></a></p>
<p>Bunun için yukarıdaki ekran görüntüsünde olduğu gibi <strong>Office/Sharepoint </strong>sekmesinde yer alan <strong>Word 2010 Document</strong> şablonunun seçilmesi yeterlidir. <strong>Word</strong> uygulaması içerisinde <strong>Team Foundation Server Client Object Model</strong> kullanılacağından ilgili <strong>Assembly</strong> referanslarının projeye eklenmesi de gerekmektedir. <em>(Bu örnek için <strong>Microsoft.TeamFoundation.Client</strong> ve <strong>Microsoft.TeamFoundation.WorkItemTracking.Client</strong> dll’ lerini eklemeliyiz)</em></p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_3.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_3" src="/pics/tfsword_3_thumb.png" alt="tfsword_3" width="343" height="511" /></a></p>
<p><strong>Word</strong> dokümanının tasarımını ise aşağıdaki ekran görüntüsünde yer aldığı gibi yapabiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_4.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_4" src="/pics/tfsword_4_thumb.png" alt="tfsword_4" width="614" height="518" /></a></p>
<p>Oldukça sade bir tasarımımız var. Örneği mümkün olduğunca basit seviyede tutmamız önemli. <strong>Product Backlog Item</strong> ile <strong>Task</strong> öğelerine ait <strong>Title</strong> ve <strong>Description</strong> girişleri için <strong>PlainTextContentControl</strong> bileşeninden yararlanılmaktadır. Ve,</p>
<h1>Kod</h1>
<p>Kullanıcı <strong>Save</strong> işlemini icra ettiğinde<em>(Ribbon kontrolüne basabilir, Ctrl+Save yapabilir vb)</em>, girdiği veri içeriğinin <strong>TFS</strong> tarafındaki ilgili projenin <strong>backlog</strong>’ una yazılması gerekmektedir. Bu nedenle odak noktası dokümanın <strong>BeforeSave</strong> olay metodudur. Lakin <strong>Client Object Model</strong> nesne referanslarının nasıl kullanıldığına da dikkat edilmelidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using Microsoft.Office.Tools.Word;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
namespace HowTo_TFSandWord
{
public partial class ThisDocument
{
#region Global değişkenler
Uri tfsAddress = new Uri("http://tfsserver:8080/tfs/defaultcollection");
TfsTeamProjectCollection collection = null;
WorkItemStore store = null;
Project argeProject = null;
WorkItemType witBacklogItem = null;
WorkItemType witTask = null;
WorkItemLinkTypeEnd linkTypeEnd = null;
#endregion Global değişkenler
private void InitializeTFSComponents()
{
collection = new TfsTeamProjectCollection(tfsAddress);
store = collection.GetService<WorkItemStore>();
argeProject = store.Projects["ARGE"];
witBacklogItem = argeProject.WorkItemTypes["Product Backlog Item"];
witTask = argeProject.WorkItemTypes["Task"];
linkTypeEnd = store.WorkItemLinkTypes.LinkTypeEnds["Parent"];
}
void ThisDocument_BeforeSave(object sender, SaveEventArgs e)
{
#region Yeni Bir Product Backlog Item Oluşturmak
int createdBacklogItemId=CreateBacklogItem(textBacklogTitle.Text, textBacklogDescription.Text);
CreateTask(createdBacklogItemId, textTask1Title.Text, textTask1Description.Text);
CreateTask(createdBacklogItemId, textTask2Title.Text, textTask2Description.Text);
#endregion Yeni Bir Product Backlog Item Oluşturmak
}
private int CreateBacklogItem(string title,string description)
{
WorkItem newBacklogItem = new WorkItem(witBacklogItem);
newBacklogItem.Title = title;
newBacklogItem.Description = description;
newBacklogItem.Save();
return newBacklogItem.Id;
}
private void CreateTask(int createdBacklogItemId,string title,string description)
{
WorkItem newTask = new WorkItem(witTask);
newTask.Title = title;
newTask.Description = description;
newTask.WorkItemLinks.Add(new WorkItemLink(linkTypeEnd, createdBacklogItemId));
newTask.Save();
}
#region VSTO Designer generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisDocument_Startup);
this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
this.BeforeSave += ThisDocument_BeforeSave;
InitializeTFSComponents();
}
#endregion
private void ThisDocument_Startup(object sender, System.EventArgs e)
{
}
private void ThisDocument_Shutdown(object sender, System.EventArgs e)
{
}
}
}</pre>
<p>Öncelikli olarak <strong>TFS</strong> sunucusuna ve ilgili koleksiyona bağlanılması gerekir. Bu amaçla <strong>TfsTeamProjectCollection</strong> sınıfından yararlanılmaktadır. Dikkat edileceği üzere <strong>yapıcı metoda<em>(Constructor)</em> </strong>parametre olarak <strong>Default</strong> <strong>Collection</strong> için kullanılabilecek adres verilmiştir. <strong>Work</strong> <strong>Item’</strong> lar üzerinde <strong>CRUD</strong> işlemlerini icra edebilmek için <strong>WorkItemStore</strong> servisine ulaşılması gerekmektedir. Bu sebepten <strong>collection</strong> değişkeni üzerinden <strong>GetService</strong> fonksiyonuna başvurulmuştur. Çok doğal olarak <strong>ARGE</strong> isimli örnek <strong>Team</strong> <strong>Project</strong> içerisine <strong>Work</strong> <strong>Item</strong> eklenmesi istenmektedir. Bu nedenle ilgili proje referansı, <strong>store</strong> değişkeni üzerinden <strong>Projects</strong> koleksiyonuna erişilerek elde edilmektedir. Gelelim <strong>Work</strong> <strong>Item</strong> oluşturma kısımlarına.</p>
<p><strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> için <strong>CreateBacklogItem</strong>, <strong>Task</strong> içinse <strong>CreateTask</strong> isimli metodlar kullanılmaktadır. Aslında her ikisi de içerisinde bir <strong>WorkItem</strong> nesnesini örneklemekte ve ilgili özelliklerini <strong>set</strong> etmektedir. Ancak önemli bir fark vardır. Bir <strong>WorkItem</strong> nesne örneği üretilirken, <strong>WorkItemType</strong> tipinden bir parametre verilir. Bu parametre, ilgili <strong>Work</strong> <strong>Item</strong> öğesinin <strong>ne</strong> olacağını belirtir. Bir <strong>Task</strong> mı, bir <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> mı, bir <strong>Bug</strong> mı vs. Bundan sonraki kısımlarda yer alan özellikler temel anlamda ortak sayılabilir. <strong>Title</strong> ve <strong>Description</strong> özelliklerine ilgili değerler <strong>set</strong> edildikten sonra, <strong>WorkItem</strong> nesne örneği üzerinden <strong>Save</strong> işleminin icra edilmesi yeterlidir.</p>
<p><strong>WorkItem</strong> nesneleri kayıt edildiğinde <strong>Id</strong> özellikleri de, sunucu tarafından verilen değer ile otomatik olarak doldurulur. Nitekim <strong>Parent-Child</strong> ilişkinin oluşturulması noktasında, <strong>Parent Work Item</strong>’ ın <strong>Id</strong> değerinin bilinmesi önemlidir. Bu sebepten <strong>CreateBacklogItem</strong> metodu geriyer üretilen <strong>Work</strong> <strong>Item</strong> <strong>Id</strong> değerini döndürmektedir. Bu değer <strong>CreateTask</strong> fonksiyonu için bir girdidir. <strong>CreateTask</strong> metodunun en kritik noktası ise <strong>WorkItemLinks</strong> koleksiyonuna <strong>Parent</strong> tipte bir bağlantı tanımının eklenmesidir. Bunun için <strong>WorkItemLinkTypeEnd</strong> ve <strong>WorkItemLink</strong> tiplerinden yararlanılmıştır. Parametre olarak gelen integer değer bu senaryo da <strong>Parent </strong>olacak <strong>Product</strong> <strong>Backlog</strong> <strong>Item’</strong> ı işaret etmektedir.</p>
<h1>Testler</h1>
<p>Artık uygulamayı test edebiliriz. Örnek olarak ben aşağıdaki ekran görüntüsünde yer alan içeriği oluşturdum.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_5.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_5" src="/pics/tfsword_5_thumb.png" alt="tfsword_5" width="607" height="448" /></a></p>
<p>Şu aşamda <strong>Save</strong> işlemini icra ettiğimizde <strong>TFS</strong> tarafında aşağıdaki içeriklerin oluştuğuna şahit olabiliriz. Dikkat edileceği üzere <strong>“Müşteri karakteristiği oluşturma”</strong> isimli bir <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> oluşturulmuş ve varsayılan olarak o anki güncel <strong>Sprint</strong>’ e ilave edilmiştir.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_6.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_6" src="/pics/tfsword_6_thumb.png" alt="tfsword_6" width="640" height="391" /></a></p>
<p><strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> açıldığında bir <strong>Id</strong> değeri aldığını ve <strong>Word</strong> dosyasında belirttiğimiz <strong>Description</strong> içeriğine sahip olduğunu da görebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_7.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_7" src="/pics/tfsword_7_thumb.png" alt="tfsword_7" width="634" height="447" /></a></p>
<p>Hatta <strong>Tasks</strong> kısmına geçtiğimizde, <strong>Child</strong> olarak bağladığımız <strong>Work</strong> <strong>Item</strong> öğelerini de görebiliriz. Dikkat edileceği üzere <strong>6539</strong> ve <strong>6540</strong> numaralı <strong>Task</strong> öğeleri <strong>Child</strong> olarak <strong>6538</strong> numaralı <strong>Product</strong> <strong>Backlog</strong>’ a eklenmiştir.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_8.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_8" src="/pics/tfsword_8_thumb.png" alt="tfsword_8" width="637" height="471" /></a></p>
<p>Pek tabi ki bu <strong>Task</strong> örneklerine çift tıklandığında, <strong>Word</strong> dosyasında belirttiğimiz <strong>Title</strong> ve <strong>Description</strong> bilgilerine sahip olduklarını görebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_9.png"><img style="display: inline;" title="tfsword_9" src="/pics/tfsword_9_thumb.png" alt="tfsword_9" width="639" height="450" /></a></p>
<p><a href="https://www.buraksenyurt.com/pics/tfsword_10.png"><img style="margin: 4px 0px; display: inline;" title="tfsword_10" src="/pics/tfsword_10_thumb.png" alt="tfsword_10" width="634" height="444" /></a></p>
<p>Her şey çok kolay görünüyor değil mi? Ama pek çok eksik ve tamamlanması gereken iş var. Bu işlerin tamamlanması da önemli bir development eforunu gerektirmekte.</p>
<h1>Eksikler</h1>
<p>Bu nokta da örneğimizin aslında sadece bir <strong>Hello</strong> <strong>World</strong> olduğunu ifade etmem gerekiyor. Sizin de fark edeceğiniz gibi bazı eksik noktalar var. Örneğin,</p>
<ul>
<li>Kullanıcı doküman içeriğini doldurmadan da göndermeyi deneyebilir. Bu durumda bir tedbir almak faydalı olacaktır. Hatta <strong>TFS</strong>’ in böyle bir durumda vereceği olası <strong>Exception</strong> tepkisine karşı bir geliştirme yapılmalıdır.</li>
<li>Akıllı bir <strong>Save</strong> mekanizması gerekebilir. Aynı <strong>Title’</strong> a sahip bir <strong>Work</strong> <strong>Item</strong> içeriğinin oluşturulmasının önüne kolayca geçilebilir<em>(WorkItem listesini çek, Title’ larını karşılaştır) </em>Ancak bire bir eşleşmeyen fakat aynı anlama gelebilen <strong>Title’</strong> lar var ise, belki kullanıcıya bir pencere ile bildirimde bulunulup aralarında seçim yapması istenebilir.</li>
<li>Örnekte sadece <strong>Title</strong> ve <strong>Description</strong> alanları doldurulmuştur. Oysaki bir <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> veya <strong>Task</strong> için set edilmesi gereken daha pek çok özellik vardır. Söz gelimi kapasite planlaması ve <strong>Velocity’</strong> nin çıkmasında önem arz eden <strong>Product</strong> <strong>Backlog</strong> <strong>Item’</strong> ın <strong>Effort</strong> ve <strong>Business</strong> <strong>Value</strong> değerleri doldurulmamıştır. Benzer şekilde <strong>Task’</strong> lar için de bir atama işlemi yapılmamıştır. Yani ilgili <strong>Task</strong> kime atanmıştır bilgisi eksiktir. <em>(Bilindiği üzere <strong>Sprint</strong> planlama toplantılarında bu tip öğeler son derece dikkatli bir şekilde tespit edilmekte ve doldurulmaktadır)</em></li>
<li>Öğeler varsayılan olarak kök <strong>Area</strong> altına atanmıştır. Ancak farklı bir <strong>Area</strong> içerisinde tutulması da istenebilir. Dolayısıyla bu bilginin dosya daha açılmadan çekilmesi ve hatta dokümanda belki de bir <strong>ComboBox</strong> ile gösterilerek seçtirilmesi düşünülmelidir<em>(<strong>Area</strong>’ ya benzer şekilde <strong>Sprint</strong> ve hatta <strong>Iteration</strong> seçimler de yaptırılabilir)</em></li>
<li>Örnekte sadece bir <strong>Product</strong> <strong>Backlog</strong> <strong>Item</strong> ve buna bağlı iki <strong>Task</strong> girilmesi senaryosuna yer verilmiştir. Oysa n adet giriş yapılabilir. Dolayısıyla daha dinamik bir içerik giriş alt yapısı hazırlanmalıdır<em>(Bu noktada <strong>Excel</strong>’ in <strong>TFS</strong> ile olan varsayılan entegrasyonuna bakmanızı öneririm)</em></li>
<li>Senaryomuzda <strong>ARGE</strong> isimli bir <strong>Team</strong> <strong>Project</strong> kullanılmaktadır. Pek ala <strong>Word</strong> dosyası açılırken kullanıcıdan bir proje seçmesi istenebilir. Bu doğal olarak bir arabirimi gerektirmektedir<em>(Hatta bu arabirimde hangi <strong>Team</strong> <strong>Project’</strong> in hangi <strong>Sprint’</strong> ine içerik girileceği bilgisi dahi sorulabilir)</em></li>
</ul>
<p>ve benzeri pek çok eksik bulunabilir. Ancak amacımıza ulaştığımızı ve her zaman ki gibi kapıyı sadece araladığımızı, ardına kadar açmak için sizin çaba sarf etmeniz gerektiğini hatırlatmak isterim. Böylece geldik bir yazımızın daha sonuna. <strong>Team Foundation Server</strong> ile ilişkili araştırmalarıma fırsat buldukça devam ediyor olacağım. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2013%2f3%2fHowTo_TFSandWord.zip">HowTo_TFSandWord.zip (208,21 kb)</a></p>2013-04-11T13:15:00+00:00team foundation serverclient object modeltfs client object modeltfs integrationtfs entegrasyonwork itemtaskproduct backlog itemscrumcmmimsfbsenyurtÇalışmakta olduğumuz Team Project’ in süreç şablonu(Process Template) ne olursa olsun(Scrum, MSF, CMMI) giriş yapılan öğeler Work Item olarak düşünülmektedir. Örneğin Scrum felsefesi göz önüne alındığında Product Backlog Item, Task, Bug, Test Case ve Impediment birer Work Item’ dır. CMMI şablonuna bakıldığında ise Requirement, Task, Bug, Change Request, Issue, Review, Risk ve Test Case birer Work Item olarak düşünülmektedir.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=37c22347-faf5-4713-90eb-5b4b3e14d7160https://www.buraksenyurt.com/trackback.axd?id=37c22347-faf5-4713-90eb-5b4b3e14d716https://www.buraksenyurt.com/post/TFS-Client-Object-Model-ile-Word-Entegrasyonu#commenthttps://www.buraksenyurt.com/syndication.axd?post=37c22347-faf5-4713-90eb-5b4b3e14d716https://www.buraksenyurt.com/post/TFS-2012-ile-Duzenli-Proje-Gelistirmee28093Hello-WorldTFS 2012 ile Düzenli Proje Geliştirme–Hello World2013-03-27T23:08:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p><strong>Team Foundation Server 2012</strong> ailesini tanımaya başladığımız <a href="http://www.youtube.com/watch?v=OSY_TkUrgPk" target="_blank">bir önceki görsel dersimizde</a>, <strong>Application Lifecycle Management(ALM)</strong>, <strong>Product Lifecycle</strong>, <strong>Process Template</strong>, <strong>Scrum </strong>gibi konulara değinmiş, alt yapıya ve mimari oluşuma yüzeysel olarak bakarak, bir <strong>Srcum</strong> iterasyonunun nasıl yürüdüğünü grafiksel gösterimle ele almıştık.</p>
<p>Yeni bölümümüzde ise, ilk olarak <strong>TFS</strong>’ in web arayüzünü örnek bir <strong>Team Project </strong>üzerinden inceliyoruz. Ayrıca örnek bir <strong>Team Project</strong>’ i bu arayüz yardımıyla <strong>Scrum</strong> şablonunda oluşturuyor, bir kaç <strong>Product Backlog Item </strong>ve <strong>Task </strong>giriyor, ilk <strong>Sprint</strong>’ i başlatıyor, ekip üyelerini seçerek kapasite planlamalarını yapıyoruz. Görsel dersimizi <strong><a href="http://www.nedirtv.com" target="_blank">Nedirtv</a></strong>’ye ait olan <a href="http://www.youtube.com/channel/UCdcmN-iq3_WwByjc5ctI9gA" target="_blank">You Tube kanalından</a> da izleyebilirsiniz.</p>
<p><iframe src="https://www.youtube.com/embed/OSY_TkUrgPk" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>Bir başka görsel dersimizde görüşmek dileğiyle hepinize mutlu günler dilerim.</p>2013-03-27T23:08:00+00:00tfsteam foundation serverscrumscrum 2.2.product backlog itemproduct backlogsprinttaskalmapplication lifecycle managementtfs web accesskanban boardvelocitydashboardtask boardmsfcmmiprocess templateteam projectteam project collectionnedirtvsprint planningsprint backlogbsenyurtTeam Foundation Server 2012 ailesini tanımaya başladığımız bir önceki görsel dersimizde, Application Lifecycle Management(ALM), Product Lifecycle, Process Template, Scrum gibi konulara değinmiş, alt yapıya ve mimari oluşuma yüzeysel olarak bakarak, bir Srcum iterasyonunun nasıl yürüdüğünü grafiksel gösterimle ele almıştık.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=08cead78-9fbf-4bfb-9b0a-ecda153ba9406https://www.buraksenyurt.com/trackback.axd?id=08cead78-9fbf-4bfb-9b0a-ecda153ba940https://www.buraksenyurt.com/post/TFS-2012-ile-Duzenli-Proje-Gelistirmee28093Hello-World#commenthttps://www.buraksenyurt.com/syndication.axd?post=08cead78-9fbf-4bfb-9b0a-ecda153ba940