Programlama konusunda ciddileştikçe videolarda, kitaplarda veya makalelerde kaçınılmaz olarak "Arayüz kodu" deyimiyle karşılaşırsınız. Ve bana hiç mantıklı gelmedi. Bir arayüz oluşturmanın ve ardından onu uygulamanın gerekliliğini sorguladım. Bu arayüzlerin ne zaman ve nerede kullanılacağını nasıl belirlerim?
Ne zaman bir eğitim izlesem ya da bir makale okusam, arayüzün ne olduğunu açıklıyorlardı, "Uygulaması olmayan bir sınıf bu", ben de "Ehmm, teşekkürler 😏" diyorum. Yani bunu zaten biliyordum; asıl bilmek istediğim şey onu neden ve ne zaman kullanacağımdı.
Bir gün Discord topluluğuna sorduğumu hatırlıyorum ve kıdemlilerden biri basitçe şöyle dedi: "Endişelenme; eninde sonunda senin için tıklayacaktır" ve öyle oldu, biraz zaman aldı ama oldu. Eğer bunu yaşıyorsanız bilin ki hepimiz oradaydık; bir arayüze neden kod yazmanız gerektiğini anlamanıza yardımcı olalım.
Yapay zeka kontrolü ele aldığından ve herkes bu konuda kendini kaybettiğinden partiye geç kalmak istemiyoruz. Web sitemize eklemek istiyoruz, ürünümüzle ilgili soruları yanıtlayan küçük bir chatbot bunu yapacak.
Örneğim için PHP kullanacağım; Rahat olduğunuz herhangi bir dili kullanmaktan çekinmeyin. Önemli olan konsept.
Chatbotumuz bu kadar basit olabilir:
<?php class ChatBot { public function ask(string $question): string { $client = new OpenAi(); $response = $client->ask($question); return $response; } }
API'lerine bağlanmak, soru sormak ve ardından yanıtı döndürmek için OpenAI
SDK'yı kullanan tek bir ask()
yöntemi vardır.
Artık chatbotumuzu kullanmaya başlayabiliriz
$bot = new ChatBot(); $response = $bot->ask('How much is product X'); // The product costs $200.
Şu ana kadar uygulama iyi görünüyor, beklendiği gibi çalışıyor ve proje konuşlandırıldı ve kullanılıyor. Ancak sohbet robotumuzun büyük ölçüde Open AI API'ye bağımlı olduğunu inkar edemeyiz; Eminim katılıyorsunuzdur.
Şimdi Açık Yapay Zeka fiyatlarının iki katına çıktığı ve artmaya devam ettiği bir senaryo düşünelim, seçeneklerimiz neler? Ya kaderimize razı olacağız ya da başka bir API arayacağız. İlk seçenek kolay, biz onlara ödeme yapmaya devam ediyoruz, 2. seçenek ise göründüğü kadar basit değil. Yeni sağlayıcının büyük olasılıkla kendi API'si ve SDK'sı olacaktır; Başlangıçta Open AI için tasarlanmış tüm sınıflar, testler ve ilgili bileşenlerde güncellemeler yapmamız gerekecek, bu çok fazla iş gerektiriyor.
Bu aynı zamanda endişeleri de artırıyor; yeni API doğruluk açısından beklentilerimizi karşılamazsa veya kesinti süresi artarsa ne olur? Peki ya aynı anda farklı sağlayıcılarla denemeler yapmak istersek? Örneğin, abone olduğumuz müşterilerimize OpenAI istemcisini sağlarken misafirler için daha basit bir API kullanmak mı istiyorsunuz? Bunun ne kadar karmaşık olabileceğini görebiliyorsunuz ve nedenini biliyor musunuz? Çünkü kodumuz kötü tasarlanmıştı.
Bir vizyonumuz yoktu; biz sadece bir API seçtik ve tamamen ona ve onun uygulanmasına bağımlıydık. Artık "Koddan arayüze" prensibi bizi tüm bunlardan kurtarabilirdi. Nasıl? Görelim.
Bir arayüz oluşturmaya başlayalım:
<?php interface AIProvider { public function ask(string $question): string; }
Arayüzümüz var, ya da benim deyimimle, bir sözleşmemiz var. Bunu uygulayalım veya kodlayalım.
<?php class OpenAi implements AIProvider { public function ask(string $question): string { $openAiSdk = new OpenAiSDK(); $response = $openAiSdk->ask($question); return "Open AI says: " . $response; } } class RandomAi implements AIProvider { public function ask(string $question): string { $randomAiSdk = new RandomAiSDK(); $response = $randomAiSdk->send($question); return "Random AI replies: " . $response->getResponse(); } }
Gerçekte hem
OpenAiSDK
hem deRandomAiSDK
yapıcı aracılığıyla enjekte edilecektir. Bu şekilde, karmaşık örnekleme mantığını, kontrolün tersine çevrilmesi olarak bilinen bir kavram olan DI kapsayıcısına devrediyoruz. Bunun nedeni, her sağlayıcının genellikle belirli yapılandırmalara ihtiyaç duymasıdır.
Artık soruları yanıtlamak için kullanabileceğimiz iki sağlayıcımız var. Uygulamalarından bağımsız olarak, bir soru sorulduğunda API'lerine bağlanıp yanıt vereceklerinden eminiz. AIProvider
sözleşmesine uymak zorundadırlar.
Artık ChatBot
aşağıdakileri yapabiliriz
class ChatBot { private AIProvider $client; // A dependency can be injected via the constructor public function __construct(AIProvider $client) { $this->client = $client; } // It can also be set via a setter method public function setClient(AIProvider $client): void { $this->client = $client; } public function ask(string $question): string { return $this->client->ask($question); } }
Örneğin, bir bağımlılığı (bu durumda
AIProvider
enjekte edebileceğiniz birden fazla yolu göstermeyi amaçladığını unutmayın. Hem kurucuları hem de ayarlayıcıları kullanmanıza gerek yoktur.
Bazı ayarlamalar yaptığımızı görebilirsiniz; artık OpenAI'ye bağımlı değiliz ve ona dair herhangi bir referans bulamazsınız. Bunun yerine sözleşmeye/arayüze bağlıyız. Ve bir şekilde bu örnekle gerçek hayatta da bağlantı kurabiliriz; hepimiz en az bir kez ChatBot
olduk.
Bir güneş paneli sistemi satın aldığınızı hayal edin. Şirket, kurulumu için teknisyenler göndermeyi vaat ediyor, gönderdikleri çalışan ne olursa olsun işin tamamlanacağına ve sonunda panellerinizi taktıracağınıza dair size güvence veriyor. Yani Josh'u ya da George'u göndermeleri umurunda değil. Biri diğerinden daha iyi olmak üzere farklı olabilirler, ancak her ikisi de panellerin kurulumu için sözleşmelidir.
Ben senin televizyonunu tamir ediyorum, biliyorsun, şirket tarafından belirtilen işi yapmakla yükümlüler gibi olmayacaklar. Hem RandomAi
hem de OpenAi
AIProvider
çalışanları olarak hareket eder; bir soru sorarsınız, onlar bir cevap verirler. Panelleri kimin kurduğunu umursamadığınız gibi, ChatBot
da işi kimin yaptığını hiç umursamamalı. Sadece sağlanan herhangi bir uygulamanın bunu yapacağını bilmesi gerekiyor.
Artık birini veya diğerini özgürce kullanabilirsiniz.
$bot = new ChatBot(); // For subscribed users $bot = new ChatBot(new OpenAi()); $response = $bot->ask('How much is Product X'); // Open AI says: 200$ // For guests $bot->setClient(new RandomAi()); $response = $bot->ask('How much is Product X'); // Random AI replies: 200$
Artık API sağlayıcısının tamamını değiştirme esnekliğine sahipsiniz ve kodunuz her zaman aynı şekilde davranacaktır. Bir arayüze kodladığınız için bu konuda herhangi bir değişiklik yapmanıza gerek yok, dolayısıyla daha önce dile getirdiğimiz endişelerin hiçbiri sorun olmayacak.
Örneğimizde, bir arayüze kodlama yaparak, SOLID ilkelerinden üçüne de saygı göstermiş olduk, bunu yaptığımızı bilmeden, biraz daha detaylandırayım.
Ayrıntılara girmeyeceğim; ilkelerin her birinin uzun bir makalesi olabilir. Bu sadece bir arayüze kodlama yaparak neler kazandığımızı gösteren kısa bir açıklamadır.
Uyduğumuz ilk prensip, kodun genişletilmeye açık, değiştirilmeye kapalı olması gerektiğini belirten Açık-Kapalı Prensibidir. Her ne kadar kulağa zor gelse de bunu başardınız. Bir düşünün, ChatBot
artık değişikliğe kapalı; koda bir daha dokunmayacağız. Başından beri hedefimiz buydu.
Ancak genişletilmeye açıktır; 3'üncü, 4'üncü, hatta 5'inci bir sağlayıcı eklesek hiçbir şey bizi durduramaz. Arayüzü uygulayabiliriz ve sınıfımız onu kutudan çıktığı gibi kullanabilir, herhangi bir değişiklik yapılmasına gerek yoktur.
Sizi tanımıyla sıkmayacağım, ancak temel olarak, sınıfları TÜM alt sınıflarıyla değiştirebileceğinizi ve bunun tersini de belirtir. Teknik olarak, tüm AI sağlayıcılarımız are-a
AIProvider
ve uygulamaları ChatBot
doğruluğunu etkilemeden birbirleriyle değiştirilebilir, ChatBot hangi sağlayıcıyı kullandığını bile bilmiyor 😂, yani evet, Bayan Liskov'a saygı duyduk. .
İtiraf etmeliyim ki, bunun kendi makalesi olabilir. Ancak basitçe söylemek gerekirse prensip, somutluklardan ziyade soyutlamalara dayanmanız gerektiğini söylüyor ve biz de tam olarak bunu yapıyoruz. Open AI gibi belirli bir sağlayıcıya değil, bir sağlayıcıya bağımlıyız.
Unutmayın, bunların hepsi bir arayüze kodladığımız için.
Güncellememeniz gerektiğini bildiğiniz bir sınıfı güncellediğinizde ve kodunuz if ifadeleriyle hacklenmeye başladığında, bir arayüze ihtiyacınız vardır. Her zaman kendinize şu soruyu sorun: Bu sınıfın gerçekten bunun nasıl yapılacağını bilmesi gerekiyor mu? Bu servis sağlayıcıyı sonsuza kadar kullanacak mıyım? Veya veritabanı sürücüsü? Değilse ne yapacağınızı biliyorsunuz.
Bununla birlikte, ona biraz zaman verin, sonunda sizin için tıklayacaktır .