Java Günlüğüm
Yazılım, Java, BT, azıcık felsefe, biraz mizah...
  • Udemy Eğitimleri
  • Temiz Kod
  • Tasarım Kalıpları
  • Hakkımda
  • Arşiv
RSS
19 Ağustos 2014

Java Kodunuzun Nesne-Merkezli Olmadığının 10 İşareti – VIII: Karmaşık metotlar.

Akin Java, Yazılım Mühendisliği

Geliştirdiğimiz Java kodunun nesne-merkezli olmadığının 10 işaretinin neler olduğunu bu yazıda listelemiş ve ilk altı maddeyi daha önce ele almıştık. Şimdi de yedinci maddeyi inceleyelim:

Karmaşık metotlar. (Complex methods.)

Aslında bu madde ile bir önceki madde (Çok sayıda metoda sahip olan sınıflar.) yapı olarak benzer özelliklere sahipler. Bu iki madde, nesne-merkezli yazılımlar için yazılım kalitesinin en temel ölçütlerindendir. Bir sınıfın sahip olduğu metot sayısı ile metotların karmaşıklık düzeyi, nesne-merkezli kod parçasının kalitesini hızlı bir şekilde ortaya koyar.

Bir sınıftaki metotların karmaşıklık düzeyini belirleyen temelde 3 etmen vardır: Metodun satır sayısı, metoda geçilen parametre sayısı ve metodun içinde verilen kararların sayısı.

Metotların uzunluğu, en basit karmaşıklık ölçütü olarak görülebilir. Ne kadar kısa metot, o kadar kaliteli kod. Ya da tersinden bakarsak ne kadar uzun metot, o kadar karmaşık kod. Uzun metot, çok iş demektir. Muhtemelen de farklı metotlarda yapılabilecek pek çok işi bir arada yapmak demektir. Halbuki her metot sadece ve sadece bir iş yapmalıdır.

“Clean Code” adlı kitabında R. Martin, sınıflar içın söylediği iki cümleyi metotlar için de tekrarlıyor:

“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.”

Yani

“Fonksiyonların ilk kuralı, onların küçük olması gerektiğidir. Fonksiyonların ikinci kuralı ise onların bundan da küçük olması gerektiğidir.”

Metotlar, iş gören yapılardır. Metotların gördüğü işler farklı seviyelerde olabilir. Bazen metotlar bir süreci başlatırlar, bazen başlatılan sürecin içindeki adımlardan birini yerine getirirler, bazen de o bir adımın içinde çok basit bir şey yaparlar.  Nesne oluşturmak ya da bir süreci yönetmek ya da ya da vergiyi hesaplamak gibi çok basit bir iş yapmak şeklinde vb. Her halukarda bir metotta tek bir iş yapılmalı. Örneğin aşağıdaki metodlarla bu durumlu açıklayalım:

public void login(String tckn, String password) throws NoSuchCustomerException, CustomerAlreadyLoggedException, WrongCustomerCredentialsException, MaxNumberOfFailedLoggingAttemptExceededException, CustomerLockedException;

login() metodunun, örneğin bir web uygulamasında web katmanından çağrılan CustomerService isimli bir servis nesnesi metodu olduğunu düşünelim. Belli ki bu metot, kullanıcı bilgileriyle, o kullanıcıyı uygulamaya kabul eden sürecin başladığı yerdir. Ve bu metotdun fırlattığı sıra dışı durumlara bakınca, bu metotta öyle bir müşteri olup olmadığına karar verilmesinden, müşterinin sistemle kilitli durumda olduğunun anlaşılmasına kadar pek çok iş yapılıyor.

	@Override
	public void login(String tckn, String password) throws NoSuchCustomerException, CustomerLockedException,
			CustomerAlreadyLoggedException, WrongCustomerCredentialsException,
			MaxNumberOfFailedLoggingAttemptExceededException {
		Customer customer = customerDao.retrieveCustomer(tckn);

		// If passwords match, customer hasn't already been locked nor logged in
		// Customer loggs in and it is now currentCustomer
		if (customer.getPassword().equals(password) & !customer.isLocked() & !customer.isLoggedIn()) {
			// customer.logsin is a property in atm.properties. If it is "yes"
			// database is updated when
			// a customer logs in. Updated part in db is CUSTOMERS.LOGGEDIN
			customer.setLoggedIn(true);
			if (customerDao.updateCustomer(customer))
			currentCustomer = customer;
			loginAttemptCount = 0;
		} else if (customer.isLoggedIn()) {
			throw new CustomerAlreadyLoggedException("Customer is already logged in. Please first log out.");
		} else if (customer.isLocked()) {
			throw new CustomerLockedException("Customer is locked. Please consult your admin.");
		} else if (!customer.getPassword().equals(password)) {
			loginAttemptCount++;
			if (loginAttemptCount == Integer.parseInt(ATMProperties.getProperty("customer.maxFailedLoginAttempt"))) {
				customer.setLocked(true);
				customerDao.updateCustomer(customer);
				throw new MaxNumberOfFailedLoggingAttemptExceededException("Max number of login attempt reached: "
						+ loginAttemptCount);
			}
			throw new WrongCustomerCredentialsException("TCKN/password is wrong.");
		}
	}

Bu şekilde, bir süreci başlatan metotlara ihtiyaç pek tabi ki vardır ama bu durum devasa metotlar yazmamızı gerektirmez. Çok açık ki bu metot çok iş yapıyor. Önce “customerDao” üzerinden Customer nesnesini getiriyor. Daha sonra nesnenin üzerindeki bilgilere bakarak o nesnenin temsil ettiği müşterinin sisteme girip giremeyeceğine karar veriyor. Bunun için de hem password kontrolü yapıyor ve yanlış password girildiğinde kilitlenme sayısına gelip gelmediğini anlıyor, hem de müşterinin zaten sistemde olup olmadığını ve daha önceden kilitlenip kilitlenmediğini kontrol ediyor. Bu metot belki şu şekilde daha sağlıklı yazılabilirdi:

	public void login(String tckn, String password) throws NoSuchCustomerException, CustomerLockedException,
			CustomerAlreadyLoggedException, WrongCustomerCredentialsException,
			MaxNumberOfFailedLoggingAttemptExceededException {
		Customer customer = customerDao.retrieveCustomer(tckn);
		loginCustomer(customer, password);
	}

Yukarıdaki login metodunun ilk haliyle sonraki, iyileştirilmiş halini kiyasladığımızda, ikinci halin çok daha kısa ve anlaşılır olduğunu, çünkü sadece tek bir iş yaptığını görebiliriz. login() metodu, login için gerekli sürecin adımlarını sırayla çağırarak, müşterinin sisteme dahil olmasını sağlamakta, varsa oluşan sıra dışı durumları bir üst ortama aktarmaktadır. Orijinal halinde bu metotta olan adımlar ise farklı beş metoda dağılmıştır:

	private void checkIfCustomerAlreadyLoggedIn(Customer customer) throws CustomerAlreadyLoggedException {
		if (customer.isLoggedIn()) {
			throw new CustomerAlreadyLoggedException("Customer is already logged in. Please first log out.");
		}
	}

	private void checkIfCustomerLocked(Customer customer) throws CustomerLockedException {
		if (customer.isLocked()) {
			throw new CustomerLockedException("Customer is locked. Please consult your admin.");
		}
	}

	private void checkCustomerPassword(Customer customer, String password) throws CustomerLockedException,
			MaxNumberOfFailedLoggingAttemptExceededException, WrongCustomerCredentialsException {
		if (!customer.getPassword().equals(password)) {
			loginAttemptCount++;
			checkLoginAttempCount(customer);
			throw new WrongCustomerCredentialsException("Wrong password!");
		}
	}
	
	private void checkLoginAttempCount(Customer customer) throws MaxNumberOfFailedLoggingAttemptExceededException{
		if (loginAttemptCount == Integer.parseInt(ATMProperties.getProperty("customer.maxFailedLoginAttempt"))) {
			lockCustomer(customer);
		}
	}
	
	private void lockCustomer(Customer customer) throws MaxNumberOfFailedLoggingAttemptExceededException{
		customer.setLocked(true);
		throw new MaxNumberOfFailedLoggingAttemptExceededException("Max number of login attempt reached: "
				+ loginAttemptCount);
	}

Yukarıdaki beş metodun her birisinin sadece ve sadece bir iş yaptığına dikkat edin.

Bence idealde metotlarımız bu kadar kısa, üçer-beşer satırdan ibaret olmalı. Eskiden fonksiyonların bir ekrandan daha uzun olmaması gerektiği söylenirdi. Benim 15’lik makinamda, Eclipse’de 11 puntoluk Consolas ile tam 80 satır, aşağıya doğru kaydırmaya gerek kalmadan tek bir ekranda görünüyor. 80 satır bir metot için çok!

R. Martin Clean Code’da, bir metodun olabildiğince 20 satırı geçmemesi gerektiğini söyler. “Refactoring in Large Software Projects” isimli kitapda da  M. Lippert ve S. Roock, mimari kötü kokulardan bahsederken bir metodun ortalama olarak 30 satırı geçmemesi gerektiğinden bahseder.

Sınıfların karmaşıklık ölçütlerinden bahsederken metot sayısını ele almış ve karşı örnekleri de göstererek, bu durumun problemlerinden bahsetmiştik. Benzer durum metotların karmaşıklığını satır sayısıyla ölçerken de geçerli. Bu konuda Steven C. MacConnell’in Code Complete kitabındaki tartışmaya bakablirsiniz.

Bir metodun aldığı argüman sayısı da o metodun karmaşıklığı hakkında bize bilgi verir. İdealde bir metoda geçilen parametre sayısının sıfır olmasını bekleriz. Bu durumda o metodu kodlamak, anlamak, test etmek vs. çok daha kolay olur. Kendisine hiç parametre geçilmediği halde içinde tonla iş yapan metot yazmak elbette mümkündür ama sonuçta satır sayısı gibi bu ölçüt de mutlak olmayıp, bize kötü kokular veren cinstendir. Gerçekte bir motodun aldığı argüman sayısı, o metodun API tasarım kalitesini belirler. Parametre sayısı constructor ve factory metotlarıyla façade rolü olan sınıfların metotlarında artabilir ama bir sistemdeki metotlara geçilen parametrelerin ortalama sayısının olabildiğince 1 civarında olması tercih edilir. PMD Code Size ölçütünün ölçümlerinden biri olan ExcessiveParameterList’de uyarı seviyesini 10 olarak belirlemiştir. Yani 10’dan fazla parametre alan metotların gözden geçirilmesini tavsiye etmektedir.

Bir diğer metot karmaşıklığı ölçütü de “Cyclomatic Complexity” denen ve 1976 yılında MacCabe tarafında geliştirilmiş olan ölçüttür. Dilimize karar karmaşıklığı olarak da çevrilebilecek bu ölçüt, bir metotta alınan kararların sayısı üzerine bina edilmiştir. Dolayısıyla bir metotaki if-else, switch-case, while, for gibi karar mekanizmaları ne kadar az kullanılırsa o kadar sağlıklı metotlara sahip oluruz. PMD Code Size ölçütünün ölçümlerinden biri olan CyclomaticComplexity’de uyarı seviyesini 10 olarak belirlemiştir. Yani 10’dan fazla karar mekanizmasına sahip olan metotların gözden geçirilmesini tavsiye etmektedir. Bu konuyu ileride daha geniş ele almak üzere burada bırakalım.

Metotlar, kodumuzun ana yapılarındandır. Bu yüzden metotların basitliği ve anlaşırlığı, sistemimizin basitliği ve anlaşırlığını belirler. Unutmayalım, “küçük güzeldir” (small is beautiful).

Toplam görüntülenme sayısı: 1008

11 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
16 Ağustos 2014

Java Kodunuzun Nesne-Merkezli Olmadığının 10 İşareti – VII: Çok sayıda metoda sahip olan sınıflar

Akin Java, Yazılım Mühendisliği code metric

Geliştirdiğimiz Java kodunun nesne-merkezli olmadığının 10 işaretinin neler olduğunu bu yazıda listelemiş ve ilk beş maddeyi ele almıştık. Şimdi de altıncı maddeyi ele alalım:

Çok sayıda metoda sahip olan sınıflar. (Classes with lots of methods.)

Sınıflarla soyutlamalar yapılır. Sınıflar, sorumlulukları ve bilgiyi sarmalar (encapsulation). Sorumluluklar ise metotlarla yerine getirilir. Dolayısıyla çok sayıda metot, çok sayıda sorumluluğa sahip olmak anlamına gelir. Sınıflar ise çok sorumluluğa sahip olmamalıdırlar. Sağlıklı sınıflar az sorumluluğa sahip sınıflardır.

Genel olarak karmaşıklık arttıkça birlikteliğin (cohesion) düştüğü kabul edilir. Çünkü karmaşık yapılar muhtemelen birden fazla şeyi bir arada hallediyorlardır. Yani karmaşık bir yapı, aslında aralarında ilişkiler olan daha basit bir kaç yapı olarak ifade edilmelidir. Bir sınıfın çok sayıda metoda sahip olması da onun karmaşıklaşması anlamına gelir. Eğer sınıfın soyutladığı kavramla ilgili çok sorumluluğu varsa, farklı sorumluluk kümeleri oluşturulmalı ve bu kümeler farklı sınıflar altında soyutlanmalıdır. Bu durumda yapılacak şey, bir sınıfa sahip olmak yerine aralarında ilişkiler bulunan birden fazla arayüz ve sınıfa sahip olmaktır.

Aslında metotlar için söylediğimiz bu durum nesnenin değişkenleri için de geçerlidir. Çok sayıda değişkene sahip olan sınıflarda da bir odaklanma problemi olduğu söylenebilir. Dolayısıyla sınıflar, değişken açısından da olabildiğinda az sayıda değişkene sahip olmalı ve bu değişkenler sınıfın soyutlamasının bir parçası olmalılar.

Tahmin edeceğiniz gibi burada bahsettiğimiz metotlar ve değişkenler, nesnelerin metotları ve değişkenleridir. Zira zaten bir sınıfta normal olarak statik değişken ve metotların sayısının çok olması o sınıfın bir soyutlama yapmayan, ancak utility vb. tipte bir sınıf olması durumunda geçerlidir.

Bir sınıfı modellerken akılda tutulması gereken ilk prensip muhtemelen “Tek Sorumuluk Prensibi”dir. “Single Responsibility Principle” diye bilinen bu prensibe göre sınıflarımız sadece ve sadece bir sorumluluk alanına sahip olmalıdır. Yani sınıflarımız sadece bir konuya odaklı olmalı, onunla ilgili sorumlulukları içermeli ve sadece sebepten dolayı değişmelidir. Sınıflarınızı kurgularken eğer birden fazla noktayı bir araya getiriyorsanız, metotlarınız arasında farklı konularla ilgili olanlar da varsa muhtemelen sınıfınız metot ve değişken sayısı yönünden çok zengin olacak ve bundan dolayı da düşük bir birlikteliğe sahip olacaktır.

Sağlıklı sınıflar elde etmek için aklımızda tutmamız gereken bir diğer prensip de “Interface Segregation Principle” yani “Arayüzlerin Ayırımı Prensibi” olabilir. Buna göre bir sınıfın clientları, o sınıfta kullanmadığı metotlar görmemelidir. Yani, sınıflarımızın arayüzlerini olabildiğince küçültmeli yani az sayıda metoda sahip olacak şekilde kurgulamalıyız. Bu amaçla eğer bir sınıf farklı sorumuluk gruplarına sahipse bu grupları farklı arayüzlerle ifade edecek şekilde ayırmalıyız.

Bu konuyu daha iyi açıklamak için şöyle örnekler verebiliriz. Bir Modem sınıfına ihtiyacımız olduğunu düşünelim. Bu sınıf önce bağlantı kuracak, sonra bağlantı üzerinden veri alış-verişi yapacak, sonra da bağlantıyı kapatacaktır. Bu amaçla şöyle bir sınıf tasarladığımızı düşünelim:

public interface Modem {
	public void dial(String pno);
	public void hangup();
	public void send(String s);
	public char receive();
}

Yukarıdaki Modem arayüzünün, temelde ayrı olarak ele alınması gereken iki farklı sorumluluk kümesini bir araya getirdiğini görüyoruz: Bağlantı kurmak ve bağlantıyı kapatmak ile veri alış-verişi aslında iki ayrı sorumluluk alanı. Eğer modem’i bu şekilde kurgularsak, modemi değiştirmek içın iki ayrı sebebimiz olacak. Öte taraftan, modem olmadığı halde bağlantı yöneten yapılar ile benzer şekilde modem olmadığı halde veri alış-verişi yapan yapıları bu yapıyla temsil etmemiz mümkün olamayacak. Yukarıdaki yapıyı iki ayrı arayüz olarak kurgulamak, tek sorumluluk prensibi ve birliktelik açısından daha iyi olurdu:

public interface Connection {
	public void dial(String pno);
	public void hangup();
}

 

public interface Communication {
	public void send(String s);
	public char receive();
}

 

public class Modem implements Connection, Communication {
	public void dial(String pno){ ... }
	public void hangup(){ ... }
	public void send(String s){ ... }
	public char receive(){ ... }
}

Bu şekilde sadece 4 metoda sahip bir yapıyı bile tek sorumluluk prensibi ile bölebiliyorsak, onlarca metoda sahip olan aşağıdaki sınıf için ne düşünürsünüz?

public class SuperDashboard extends JFrame implements MetaDataUser {
 public String getCustomizerLanguagePath()
 public void setSystemConfigPath(String systemConfigPath)
 public String getSystemConfigDocument()
 public void setSystemConfigDocument(String 
                                          systemConfigDocument)
 public boolean getGuruState()
 public boolean getNoviceState()
 public boolean getOpenSourceState()
 public void showObject(MetaObject object)
 public void showProgress(String s)
 public boolean isMetadataDirty()
 public void setIsMetadataDirty(boolean isMetadataDirty)
 public Component getLastFocusedComponent()
 public void setLastFocused(Component lastFocused)
 public void setMouseSelectState(boolean isMouseSelected)
 public boolean isMouseSelected()
 public LanguageManager getLanguageManager()
 public Project getProject()
 public Project getFirstProject()
 public Project getLastProject()
 public String getNewProjectName()
 public void setComponentSizes(Dimension dim)
 public String getCurrentDir()
 public void setCurrentDir(String newDir)
 public void updateStatus(int dotPos, int markPos)
 public Class[] getDataBaseClasses()
 public MetadataFeeder getMetadataFeeder()
 public void addProject(Project project)
 public boolean setCurrentProject(Project project)
 public boolean removeProject(Project project)
 public MetaProjectHeader getProgramMetadata()
 public void resetDashboard()
 public Project loadProject(String fileName, String projectName)
 public void setCanSaveMetadata(boolean canSave)
 public MetaObject getSelectedObject()
 public void deselectObjects()
 public void setProject(Project project)
 public void editorAction(String actionName, ActionEvent event)
 public void setMode(int mode)
 public FileManager getFileManager()
 public void setFileManager(FileManager fileManager)
 public ConfigManager getConfigManager()
 public void setConfigManager(ConfigManager configManager)
 public ClassLoader getClassLoader()
 public void setClassLoader(ClassLoader classLoader)
 public Properties getProps()
 public String getUserHome()
 public String getBaseDir()
 public int getMajorVersionNumber()
 public int getMinorVersionNumber()
 public int getBuildNumber()
 public MetaObject pasting(
 MetaObject target, MetaObject pasted, MetaProject project)
 public void processMenuItems(MetaObject metaObject)
 public void processMenuSeparators(MetaObject metaObject)
 public void processTabPages(MetaObject metaObject)
 public void processPlacement(MetaObject object)
 public void processCreateLayout(MetaObject object)
 public void updateDisplayLayer(MetaObject object, 
                                                 int layerIndex)
 public void propertyEditedRepaint(MetaObject object)
 public void processDeleteObject(MetaObject object)
 public boolean getAttachedToDesigner()
 public void processProjectChangedState(boolean 
                                        hasProjectChanged)
 public void processObjectNameChanged(MetaObject object)
 public void runProject()
 public void setAçowDragging(boolean allowDragging)
 public boolean allowDragging()
 public boolean isCustomizing()
 public void setTitle(String title)
 public IdeMenuBar getIdeMenuBar()
 public void showHelper(MetaObject metaObject, 
                        String propertyName)
 // ... many non-public methods follow ...
}

Yukarıdaki sınıfı R. Martin’in Clean Code kitabından aldım ama emin olun bu sınıf kadar odaksız, gelişi güzel yazılmışlarını ben de çok gördüm. Danışmanlıklarım sırasında o kadar baştan savma, hiç bir tasarım kırıntısı taşımayan ve sonrasında da farklı faktörlerle büyümüş, devasa boyutlara ulaşmış sınıflar gördüm ki.

Martin, Clean Code kitabında sınıflar hakkında şöyle der:

“The first rule of classes is that they should be small. The second rule of classes is that they should be smaller than that.”

Yani

“Sınıflarla ilgili ilk kural, onların küçük olması gerektiğidir. Sınıfların ikinci kuralı ise onların bundan da küçük olması gerektiğidir.”

“Refactoring in Large Software Projects” isimli kitapda da  M. Lippert ve S. Roock, mimari kötü kokulardan bahsederken bir sınıfta ortalama olarak 30’dan az metot olması gerektiğinden bahseder. (Lippert ve Roock kitaplarında genelde bir seviyede, alt seviyedeki elementlerden en çok 30 tane olması gerektiğini söylerler. Bir pakette 30 tip, bir tipte 30 metot, gibi.)

Bir kodu iyileştirmek istediğimde ilk yapmak istediğim şey genelde o kodu, küçük parçalara bölmektir. Büyük sınıfları, küçük sınıflara, büyük metotları küçük metotlara çevirmek, o kod parçasını çok daha anlaşılır, test edilir ve değiştirilebilir yapacaktır.

Bir kod kalitesi aracı olan PDM de “code size” kalite ölçeğinde birden fazla büyüklük ölçümüne sahiptir. Bu ölçümlerden “TooManyMethods”un ölçum sınırı 10’dur. Yani PDM, 10’dan fazla metoda sahip sınıflar için uyarı vermektedir. PMD benzer şekilde 15’ten fazla alana sahip olan sınıflar için de “TooManyFields” uyarısı üretmektedir. Bu durum da, en başta da belirttiğimiz gibi sonuçta bir odaklanma probleminin işaretidir.

Metot sayısının çokluğu açısından eleştirilemeyecek sınıfların olmasını düşünmek anormal bir durum değildir. Muhtemelen teme veri yapıları ya da iş nesneleri cinsinden en temel soyutlamaların, daha fazla syıda metota sahip olma eğiliminde oldukları söylenebilir. Bu duruma bol miktarda oveloaded metotlara sahip olan utility sınıfları da dahildir.

İşin açıkçası, bir sınıfın kalitesini sadece metot sayısına indirgemek itiraz edilecek bir durumdur. Örneğin Java SE’nin 8 sürümündeki java.lang.String sınıfı üzerinde 15 constructor ve 15’i statik, 52’si nesne metodu olmak üzere toplam 67 tane metot vardır. Bu metotlardan sadece bir tanesi deprecated olarak işaretlenmiştir. java.lang.Object sınıfından devralınan ve bu sınıfta override edilen metotları çıkarsak bile String sınıfının 60 civarında metoda sahip olduğu söylenebilir. Benzer durum java.lang.Math sınıfı için de geçerlidir. Math sınıfındaki tüm metotlar statiktir ve toplam 73 tanedir. Peki bu duruma ne deriz? Aslında metot ya da satır sayısı cinsinden tamamen sayısal değerlendirmelerin, bir sınıfın kalitesi hakkında her şeyi söylemediğini, daha karmaşık ve anlama yönelik kalite kriterlerinin olması gerektiğini ifade edebiliriz. Bu durum zaten kaynaklarda da tartışılmakta ve farklı önerilere ve çalışmalara konu olmaktadır. Bence çok bilimsel çalışmadığımız durumlarda, tersini anlayıncaya kadar büyüklük bir kötü koku sebebidir, üzerine gitmekte fayda vardır.

Schumacher’in dediği gibi “küçük güzeldir” (small is beautiful) ve büyük olmanın işe yarayacağını kanıtlayıncaya kadar sınıflarımızı küçük tutalım.

Toplam görüntülenme sayısı: 960

11 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
14 Ağustos 2014

Programcı, Developer, Architect (Mimar), Bilgisayar Mühendisi ve Yazılım Mühendisi – III

Akin Java, Yazılım Mühendisliği

Bu serinin ilk iki yazısında programcı, developer ve yazılım mimarı pozisyonlarını ele almıştım. Şimdi de yazılım mühendisini ele alalım.

Yazılım mühendisliği, daha önce ele aldığımız programcılık, developerlık ve yazılım mimarlığından çok daha farklı, tüm bu pozisyonlar yanında pek çok diğer pozisyonun da içinde olduğu yazılım geliştirme sürecini tasarlayan ve işletilmesini sağlayan kişidir. Dolayısıyla yazılım mühendisi, yazılım geliştirmedeki, iş ve ihtiyaç analizi, mimari ve fonksiyonel tasarım, kodlama, yazılım kalitesi ve test, bakım, proje yönetimi, değişim ve konfigürasyon yönetimi ve dokümantasyon gibi konularda süreçsel kurgulamalar ve yönlendirmelerden sorumludur. Bu anlamda yazılım mühendisi ne programcıdır, ne developerdır, ne mimardır ne de proje yöneticisidir. Yazılım mühendisi bunlardan hiç birisidir ama tüm bu pozisyonların yaptıklarını, büyük resimde, anlamlı bir süreç olarak kurgulayandır. Bulunduğu ortamda yazılımın, yazılım mühendisliği disiplinine göre geliştirilmesini sağlar. Yazılım mühendisi, yapılan işin “program” olmaktan ne kadar uzaklaşıp, “yazılım” olmaya ne kadar yaklaşacağını, ortaya karışık bir yapı mı yoksa kontrollü bir sistem mi çıkacağını belirleyen, yazılım geliştirmenin kaotik bir aktiviteler zinciri yerine, tanımlı, yinelenebilen ve ölçülebilen bir süreç olarak yerine getirilmesini   sağlayan kişidir.

Pek tabi olarak bir yazılım mühendisinin yukarıda saydığımız konuların hepsinde uzman olmasını bekleyemeyiz. Ama örneğin bir yazılım mühendisi ya iş ve ihtiyaç analizinin nasıl yapılacağını bilir, işin süreçlerini, iş kurallarını, entegrasyon noktalarını, kısıtlarını yani özetle, fonksiyonel olan ve olmayan ihtiyaçlarını ortaya koyar ya da bunları yapan iş ve ihtiyaç analistleriyle yakın çalışır, süreçte bulunur, çıktıları kullanır, yani bir şekilde o sürecin uzmanıyla ortak çalışabilir. Benzer şekilde yazılım mühendisi eğer daha çok modelleme tarafında bulunuyorsa, çıkarılan ihtiyaçların nesne-merkezli programlamaya izin verecek şekilde nesne modellenmesini, veri-merkezli yapılara el verecek şekilde E-R veri modellemesini yapar. Durum diyagramları vb. teknikleri kullanarak farklı mahiyetteki nesneleri modeller, tasarım şablonlarını uygular.

Yazılım mühendisi, literatürde var olan farklı yaklaşımlardan haberdardır ve en az birisini bilir. Örneğin yazılım mühendisi iş ve ihtiyaç analizinin use-caseler kullanılarak nasıl yapıldığını bilir, yapanlarla konu üzerine konuşabilir. Ya da nesne modellemede var olan yaklaşımlardan en az birinden haberdardır ve uygulayabilir. Domain-driven design, aspect-oriented programming, test-driven design vb. yaklaşım ve teknikleri yakınen takip eder ve uygun gördüklerinin bulunduğu ortamda yaygınlaşmasını sağlar.

Yazılım mühendisi, waterfall, extreme programming, Scrum vb. yazılım geliştirme süreci yaklaşımlarından da haberdardır. Tabi olarak hepsinde uzman olmasını bekleyemeyiz ama en azından örneğin iterative ve incremental metodolojilerin temel felsefesini ve tekniklerini bilir ve uygular.

Yukarıda anlatılanlar ışığından bakıldığında ülkemizde yazılım geliştiren kurumlarda bir yazılım mühendisliği yaklaşımının ve kültürünün olduğunu söylemek pek de mümkün değildir. Sektör olarak yazılım geliştirmeyi süreç odaklı bir mühendislik disiplini olarak görmek yerine, programlamadan ibaret ele aldığımız için, kaliteli, öngörülebilir, tekrarlanabilir yazılım geliştirme yaklaşımlarına da sahip değiliz malesef. Yazılım mühendisliği konusunda eğitim veren lisans ve lisans üstü düzeyinde yüksek ögrenim kurumları olmasına rağmen ne bunlar yeterli sayıdalar ne de bu kurumlarda gerçekten, güncel ve uygulanabilir bir yazılım mühendisliği altyapısı ve pratiği öğretilmektedir. (Açıkçası yazılım mühendisliğinin, lisans düzeyinde ögretilmesiyle ilgili şüphelerim de var. Bu kadar kapsamlı ve iş ve ihtiyaç analizi, programlama, yazılım mimarisi, yazılım kalitesi vb. çok yoğun bilgi gerektiren alt disiplinlerden en az birinde ciddi bilgi sahibi olmadan, bir lise mezununun doğrudan yazılım mühendisliği okuması bana çok anlamlı gelmiyor. Ben yazılım muhendisliği eğitiminin lisans üstü seviyesinde verilmesini ve burada eğitim almak isteyenlerin, aynen MBA ya da PMP konularında olduğu gibi, BT dünyasında ilgili pozisyonlarda örneğin minimum 5 sene tecrübeye sahip kişiler olması gerektiğini düşünüyorum.)

Ben uzun süredir yazılım mühendisliği konularında eğitimler hazırlıyorum, veriyorum ve danışmanlık hizmeti sağlıyorum. Eğitimler arasında yazılım geliştirme süreçlerini baştan sona anlatanlar olduğu gibi sadece örneğin iş ve ihtiyaç analizine ya da nesne-merkezli tasarıma odaklı eğitimler de var. Ama bu tür süreç eğitimlerine ilgi malesef o kadar az ki! Aynı şey danışmanlıklar için de geçerli. Sadece bu tür süreç eğitimlerine ve danışmanlıklarına odaklı iş yapmaya kalksam muhtemelen aç kalırdım. Bu yüzden gerek eğitim olsun gerek danışmanlık olsun, vaktimin çoğunu Java teknolojileri ve mimarisiyle ilgil eğitim ve danışmanlıklar alıyor. Malesef gerek toplum gerek ise sektör olarak son derece teknoloji odaklıyız. Teknolojiyi kullanarak nasıl katma değer yaratacağımızı düşünmeden, sanki teknolojinin bizatihi kendisi bir değermiş gibi, ona son derece yüksek harcamalar yaparken, teknolojiyi doğru olarak nasıl kullanmamız gerektiğine ne zaman ne de kaynak ayırıyoruz.

Aslında bu yazıyı yazarken aklıma gelen bir örnek var. Devlet, farklı iş kollarındaki iş yerlerine, o konunun uzmanı olan mühendislerin çalıştırılmasını zorunlu tutuyor. Farklı gıda üreticilerinde gıda mühendislerinin ya da ziraat mühendislerinin çalıştırılması zorunluluğu gibi. Benzer şekilde yazılım geliştiren kurumlarda da sanki, geliştirmeyi daha sağlıklı yapmalarını temin etmek üzere belli sayıda yazılım mühendisi istihdam etmelerini zorunlu tutmak iyi olur diye düşündüm. Bunun naif bir düşünce olduğunun farkındayım 🙂 Ama demek istediğim, kaotik geliştirme kültüründen, öngörülebilen ve kontrol edilebilen bir geliştirme kültürüne geçemediğimiz müddetçe bence bu topraklardan dünya piyasalarına sunulacak yazılım ürünleri ve çözümlerinin çıkması çok zor. Bırakın dünyaya yazılım ürünleri ve hizmetleri ihraç etmeyi, yurt içinde “ürün” yani “product” tanımına uyacak bir yazılım çıktısı bulmak bile güçtür. Bir ülkede güçlü bir iç yazılım pazarı ve üreticileri yoksa, o ülkenin bu sektörünün zaten dünyadaki pazarlarda yer alması mümkün değildir.

Zaman zaman, programcılık dışında herhangi bir yazılım aktivitesinde bulunmayan, kariyerinin başındaki kişilerin kendilerini “yazılım mühendisi” olarak tanıttıklarına ya da kurumların bu kişilere bu ünvanı verdiklerine şahit oluyorum. Yazılım geliştirmeyi bir süreç olarak algılamayan, sadece program geliştirip ve programcılık yaparken, bu şekilde çalışmayan kişi ve kurumların, kartvizitlerinde “Yazılım Mühendisi” ünvanını kullanması bence traji-komik bir durum oluşturuyor.

Yazılım mühendisliğine giriş yapmak, kendini bu alanda geliştirmek isteyen programcı, developer, analist vb. pozisyonlarda çalışan kişiler, bu konuda yüksek lisans eğitimi almayı düşünebilirler. Ya da yazılım mühendisliğini bir süreç olarak ele alıp anlatan kitaplardan faydalanabilirler. Son 10-15 yılda, agile metodolojiler üzerine yazılan tonla kitap, makale, yapılan konferanslar vs. ile çok ciddi bir bilgi birikimi oluştu zaten. Bunları okuyan yazılım projesi çalışanları, yazılım mühendisliğiyle ilgili çok güzel bir anlayışa sahip olabilirler. Yazılım mühendisliğindeki örneğin yazılım kalitesi gibi konulara eğilip, bu alanlarda kendilerini geliştirebilirler. Ben bir yazılım projesinde bulunan herkesin, 3-5 günlük de olsa bir şekilde bir yazılım mühendisliği eğitimi alması gerektiğini düşünüyorum. Aslında, daha doğru düzgün iş yapmak isteyen her yazılım projesi çalışanı yazılım mühendisliği konusunda kendini geliştirmeli. Aksi taktirde herkes eleştiriyor ama kimse doğrunun nasıl olması gerektiğini bilmez durumda oluyor. Örneğin developerlar ve programcılar, hem aşırı yük altında eziliyorlar hem de kalkıp sürecin  aslında nasıl olması gerektiği hakkında ciddi bilgi ve fikirlere sahip olamıyorlar, önerileri noktasal atış düzeyinde kalıyor.

Bu eğitimi bence ülkemizde BT sektörünün yöneticileri almalı. Çünkü kafasında bir yazılım mühendisliği nosyonu olmayan yöneticiler malesef çalışanlarının, özellikle de developer ve analistlerinin ensesinde boza pişiriyor çünkü yazılımın tabiatı, “ne”liği, süreçleri ve örneğin kalitesi ve riskleri hakkında hemen hiç bilgi sahibi değiller. Ve inanın, yazılım projelerinde alt seviyelerde çalışıp da sıkıntı çeken herkesin malesef yazılımı bilmeyen bir yöneticisi var.

Projelerimizi, daha mühendisce geliştirmek umuduyla 🙂

 

Toplam görüntülenme sayısı: 2092

16 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
11 Ağustos 2014

Programcı, Developer, Architect (Mimar), Bilgisayar Mühendisi ve Yazılım Mühendisi – II

Akin Java, Yazılım Mühendisliği

Bir önceki yazıda programcı ve developerdan bahsettik, konumuza devam edelim.

Architect ya da mimar, geliştirilecek olan yazılım sisteminin yüksek seviyeli tasarımını yapan kişidir. Mimar, yazılım bileşenleri ile temel özelliklerini, aralarındaki iş bölümünü ve iletişimi, katmanlar ve aralarındaki ilişkileri, kullanılacak teknolojileri, donanım altyapısı vb. sistem özelliklerini, performans, güvenilirlik (reliability) gibi fonksiyonel olmayan ihtiyaçları yerine getirecek şekilde belirler. Bu açıklamadan da anlaşılacağı gibi mimar, fonksiyonel yapıları, her türlü detayıyla tasarlayan kişi değildir. Bu anlamda yazılım mimarı, mimari olarak kritik olan fonksiyonel yapılar üzerinden hareket eder, sistemin yüksek seviyeli özelliklerini ve haritasını bu kritik fonksiyonel yapıları kullanarak belirler, detaylı fonksiyonel tasarıma girmez.

Böyle bir pozisyon, açıklamasından da anlaşılacağı gibi, öyle pat diye bir-iki senede elde edilecek tecrübe ile doldurulamaz. Kaldı ki sadece tecrübe ile de doldurulacak bir pozisyon değildir yazılım mimarlığı. Soyut ve sistem bazında düşünme becerileri çok önemlidir. Örneğin bileşenlerin API tasarımını yapmak, ön bellek kullanımı (caching) kurgulamak, transactional yapılara karar vermek, kullanılacak teknolojilerin mesela performans açısından en iyi kullanımları (best practices) belirlemek, alınan kararların UML gibi formal bir yolla dokümante etmek ve yaygınlaştırmak vs. bu anlamda mimarın yapması gereken işlerdendir. (İşin açıkcası kurumun ve projenin büyüklüğüne göre, veri, integrasyon, uygulama vb. konularda ayrı ayrı mimarlara ihtiyaç duyulabilir. Bu durumda kurumsal mimarinin (enterprise architecture) farklı vechelerinden bahsediyoruz demektir. Burada ele aldığımız daha çok uygulama ya da çözüm mimarıdır.) Yazılım mimarı, yüksek seviyeli bu gibi kararların alınmasında öncü durumdadır ama muhtemelen etrafındaki developerlarla çalışarak ilerler. Aldığı kararların tüm yazılım geliştirme takımı tarafından benimsenmesi ve sürekli bir şekilde uygulanması için takım ile iletişimini sürekli olarak korur. Bu anlamda yazılım mimarı bürokratik olarak yazılım geliştirme biriminde olmasa bile projede takımın bir parçası olur. Hatta benim gözlemlediğim, ülkemizdeki pek çok yazılım projesinde çalışan mimarlar, yazılım da gelişiren, kritik ve öneli bileşenlerin geliştirme sorumluluğunu üzerinde tutan kişilerdir.

Ülkemizde bildiği iki teknolojiyi bir araya getirip yazılım geliştiren herkes kendini mimar yerine koyuyor. Böyle bir algı, yazılım mimarisi kavramını sadece teknoloji seçimine indirgeme basitliğinin bir sonucudur. Yani örneğin Java EE teknolojilerinden hangilerinin kullanılacağına karar vermek, mesela web tarafında JSF, orta katmanda Spring, arkada, veri tabanı iletişiminde JPA kullanmaya karar vermeyi, yazılım mimarının tek yapacağı iş olarak görmenin sonucudur. Halbuki mimarlık programcılıktan farklıdır ve sadece zamanla elde edilecek bir sıfat da değildir. Sonuçta iyi mimarlar iyi programcılık geçmişine sahip kişilerdir ama her programcı hayatının ilerleyen zamanlarda otomatik olarak mimar olacak demek değildir. Bu anlamda malesef bu ülkede yazılım mimarlığı, programcılığın ya da developerlığın tabi bir uzantısı olarak görülüyor. Bu roller, pek çok ortak yönleri olsa ve birbirlerine çok yakın çalışsalar da sonuçta farklı yetki ve görevleri olan kişiler. Ben senelerce belli teknolojilerde uzmanlaşmış ama soyut düşünce yeteneklerini geliştirmeye ağirlık vermemiş, teknolojsini ve iş alanını çok iyi bilen kişilerle tanıştım ve çalıştım.

Yazılım projelerinde iyi-kötü bir mimari yapının kurgulanması ve tüm takım tarafından uygulanması, o yazılımın daha tutarlı, daha yeknesak, birlikteliğinin (cohesion) daha yüksek olmasını sağlar. Merkezi olarak alınmayan kararlar nihayetinde yazılım sisteminin aynı şeyi pek çok yerde tekrarlayan, bileşenleri arasında kaotik bir iletişime sahip hale getirir. Mimari kararların, farkında bile olmadan sadece developer/programcılar tarafından alındığı bir yerde sistemin sonunda değişemez, performans, scalability gibi açılardan çıkmaza girmiş hale gelmesi kaçınılmazdır.

“No Silver Bullet” isimli makalesinin sonunda F. Brooks, yazılımın asli zorluklarına çözümler ya da “silver bullet” (gümüş kurşun ya da daha anlamlı bir Türkçeyle ifade etmek istersek, sihirli değnek) önerirken “great designers” yani “mükemmel tasarımcılar”dan bahseder. Makalenin yazıldığı 1987 yılında tasarımcı, mimar vb. ayırımların henüz çok farkında değildik, bu yüzden bu ayırıma takılmadan Brooks’un “mükemmel yazılım mimarları”ndan bahsettiğini iddia edebiliriz. Yazılım geliştirmenin yaratıcılık gerektiren bir süreç olduğunu, dolayısıyla en iyi uygulamaları bilen kişilerin, doğru kavramsal modelleri ortaya koyabileceklerini ifade eder Brooks. Sonra da mükemmel mimarların, mükemmel yöneticiler gibi çok az bulunduğunu vurgular. Bu yüzden Brooks, kurumlara, bünyelerindeki “mükemmel tasarımcı” adaylarını erkenden bulup, onları yetiştirmelerini tavsiye eder.

Kariyerine yazılım mimari olarak devam etmek isteyen arkadaşların yazılım mimarisi kitaplarını okumaları, uygulama, veri, entegrasyon vb. konulardaki mimari yaklaşıkmları bilmeleri, farklı seviyelerde tasarım çalışmalarında bulunmaları, tasarım ve mimari kalıpları özümsemeleri, kullandıkları dilleri ve bu dillerdeki bileşen ve çerçeve (framework) yapılarını, bu teknolojilerin en iyi uygulamalarını iyice öğrenmeleri, performans, ölçeklenirlik gibi mimari konular üzerine çalışmaları ve soyut tasarım çalışmalarını ifade etmek için gerekli UML gibi formal yapıları ögrenmeleri gereklidir.

Kaliteli yazılımlar için kaliteli yazılım mimarlarına ihtiyacımız var.

 

Toplam görüntülenme sayısı: 1745

20 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
«< 37 38 39 40 41 >»

Günlüğüme Hoşgeldiniz

Bu günlükte, Yazılım Mühendisliği, Bilgi Teknolojileri, Java, kişisel gelişim ve zaman zaman da diğer konulardaki düşüncelerimi sizlerle paylaşacağım. Umarım beğenir ve hoşça vakit geçirirsiniz.

Her türlü düşüncenizi, yorum olsun, beğeni ya da eleştiri olsun, bana iletmenizi rica ediyorum sizden. Ayrıca bana akin@javaturk.org adresinden ya da Twitter'dan ulaşabilirsiniz. Videolarıma da buradan ulaşabilirsiniz.

Teşekkür ederim.

Akın Kaldıroğlu

Rahat Okumak İçin

A Decrease font size. A Reset font size. A Increase font size.

Sosyal Medya

  • Twitter
  • Facebook
  • LinkedIn
  • Youtube

Son Twitlerim

→ Takip Etmek İçin

Abone Olun

Emalinizi girerek yazılardan haberdar olun.
Loading

Son Yazılarım

  • Udemy Eğitimlerim Üzerine
  • (başlıksız)
  • Clean Code / Temiz Kod Eğitimi Udemy’de
  • Java ile Nesne-Merkezli Programlamaya Giriş Eğitimi Udemy’de
  • Selsoft Video Eğitimleri
  • Spring ile Kurumsal Yazılım Geliştirme
  • Corona Günlerinde Design Patterns
  • Corona Günlerinde Java
  • JDK 10 ve “var” Özelliği
  • Onur Özcan
  • Analist ve İş Bilgisi
  • Farklı Dillerin Bakış Açısıyla Nesne-Merkezli Programlama
  • Java Nedir?
  • Bilgi Teknolojilerinde Yetenek Yönetimi – II: Tanımlar ve Eleştiriler – I
  • Alelade Hikayeler – II: Bir Başka Performans Problemi

Yazı Kategorileri

Yazı Takvimi

Mart 2026
P S Ç P C C P
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
« May    

Yazı Arşivi

Blogroll

  • Binnur Kurt'un Günlüğü
  • Ender'in Java Blogu
  • Erdem Seherler
  • Kızımın Günlüğü
  • Kurumsal Java
  • Levent Karagöl
  • Levent'in Java Blogu
  • Mert Can Akkan’s java tips,options, news…
  • Yaşar Safkan
  • Yasin Saygılı
  • Yazı Dünyası

Yazı Etiketleri

analiz Bilmek C Desen design pattern EJB Eğitim Fortran Hibernate Java Java'ya nasil baslarim Java dersleri Java EE Java Persistence API Java SE Java Sertifika Java Öğren Java öğreniyorum Java öğrenmek JPA Kalıp Kurumsal Java nesne nesne-merkezli No Silver Bullet object object-oriented Oracle Java Certifications pattern performans programlama programlama dilleri programlama nedir sertifika singleton tasarım tasarım deseni tasarım desenleri tasarım şablonu yazılım yazılım geliştirme Yazılım Mühendisliği yazılımın doğası yazılımın zorlukları Şablon

↑

© Java Günlüğüm 2026
Powered by WordPress • Themify WordPress Themes
 

Yorumlar Yükleniyor...