Interface(arayüz) kavramı en temel ve basit anlamda, bir nesnenin diğer nesnelerle nasıl ilişki/etkileşim kurabileceğini tanımlayan ve özetleyen yapıdır diyebiliriz. Interfaceler için belirli işlevler tanımlanır, ancak bu işlevlerin nasıl gerçekleşeceğine veya logicine ilişkin bir bilgi bulunmaz, diğer bir deyişle metodların sadece imzaları bulunur gövdeleri yer almaz, bu sayede de günün sonunda elimizde nesnemizin hangi işlevleri uygulaması gerektiğine ilişkin bilgileri içeren bir kontrat veya sözleşme olmuş olur. Interface yapısı OOP paradigmasının sıklıkla kullanılan ve en güçlü özelliklerinden biridir diyebiliriz, SOLID prensiplerinede göz attığımızda interfacein önemini açıkça görebiliriz. Kodun yeniden kullanılabilirliğini artırır, bağımlılıkları azaltır ve kodun daha okunaklı ve anlaşılır olmasını sağlar, polimorfizmi destekleyerek gelişime açık değişime kapalı bir yapıyı oluşturmanın temellerinden biridir vs. gibi bir çok işlevselliği sağlamaktadır.
Örnek senaryo üzerinden gidecek olursak, geliştirdiğiniz uygulamada farklı ortamlarda veya farklı formatlarda loglama yapma ihtiyacınız olsun, anlık olarak web servera gelen requestleri Console üzerinde loglarken, sayfaları açan kullanıcıların kimliğini File üzerinde loglayalım.
package main
import (
"fmt"
"log"
"os"
)
func main() {
var serviceEndpoint = "/hello"
var logger Logger
logger = ConsoleLogger{}
logger.Log(fmt.Sprintf("GET 127.0.0.1:8000%v", serviceEndpoint))
logger = FileLogger{}
logger.Log(fmt.Sprintf("%v page hit from anonymous user", serviceEndpoint))
}
type Logger interface {
Log(message string)
}
type ConsoleLogger struct {
}
type FileLogger struct {
}
func (c ConsoleLogger) Log(message string) {
fmt.Println(message)
}
func (f FileLogger) Log(message string) {
file, err := os.OpenFile("app_logs.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Panicf("Error opening file: %v", err)
}
defer func() {
if err := file.Close(); err != nil {
log.Panicf("Error closing file: %v", err)
}
}()
log.SetOutput(file)
log.Println(message)
}
-----------------------------------------------------------------------
Output:
GET 127.0.0.1:8000/hello
app_logs.log > 2023/04/20 23:32:42 /hello page hit from anonymous user
Örneği incelediğimizde file logger veya console logger nesneleri birbirinin yerine kullanılabiliyor, ayrıca daha bu nesneleri oluşturmadan önce ne işlevleri yapacağını biliyoruz ve yine bu nesnelerle ilgili işlem yapacağımızda doğrudan nesnelere erişmek zorunda değiliz.
Interfaceler ile ilgili dikkat edilmesi gereken en önemli hususlardan biri ise, gereksiz veya ezbere kullanım diyebiliriz, kodlarken sıklıkla yapılan bir hata olan overthinking buna yol açan sebeplerden biri aslında, durum böyle olunca kodu karmaşıklaştırmaktan veya gelecekteki bakım maliyetini artırmaktan başka bir işlevi olmayan yapılar yaratmamak için tasarım ve uygulama sürecinde dikkatli davranmak gerekiyor.
Be First to Comment