Phoenix ile Tanışın: Elixir'de Modern Web Uygulamaları için Raylara Benzer Bir Çerçeve

Yayınlanan: 2022-03-11

Phoenix çerçevesi hızla popülerlik kazanarak Ruby on Rails gibi çerçevelerin üretkenliğini sunarken aynı zamanda mevcut en hızlı çerçevelerden biridir. Üretkenliği artırmak için performanstan ödün vermeniz gerektiği efsanesini kırar.

Peki Phoenix tam olarak nedir?

Phoenix, Elixir programlama dili ile oluşturulmuş bir web çerçevesidir. Erlang VM üzerine inşa edilen Elixir, modern web uygulamalarının giderek daha gerekli nitelikleri olan düşük gecikmeli, hataya dayanıklı, dağıtılmış sistemler oluşturmak için kullanılır. Elixir hakkında daha fazla bilgiyi bu blog gönderisinden veya resmi rehberlerinden edinebilirsiniz.

Bir Ruby on Rails geliştiricisiyseniz, vaat ettiği performans kazanımları nedeniyle Phoenix'e kesinlikle ilgi duymalısınız. Diğer çerçevelerin geliştiricileri de Phoenix'in web geliştirmeye nasıl yaklaştığını görmek için takip edebilir.

Elixir'de Phoenix ile Tanışın: Modern Web Uygulamaları için Raylara Benzer Bir Çerçeve

Bu yazıda, Ruby on Rails dünyasından geliyorsanız Phoenix'te aklınızda bulundurmanız gereken bazı şeyleri öğreneceğiz.

Ruby'den farklı olarak Elixir, muhtemelen uğraşmanız gerekebilecek en büyük fark olan işlevsel bir programlama dilidir. Ancak, bu iki platform arasında Phoenix'i öğrenen herkesin üretkenliklerini en üst düzeye çıkarmak için bilmesi gereken bazı önemli farklılıklar vardır.

Adlandırma kuralları daha basittir.

Bu küçük ama Ruby on Rails'den geliyorsanız ortalığı karıştırmak kolaydır.

Phoenix'te gelenek, her şeyi tekil biçimde yazmaktır. Böylece Ruby on Rails'de olduğu gibi bir "UsersController" yerine bir "UserController"ınız olur. Bu, kuralın tabloyu çoğul biçimde adlandırmak olduğu veritabanı tablolarını adlandırma dışında her yerde geçerlidir.

Ruby on Rails'de çoğul biçimin ne zaman ve nerede kullanılacağını öğrendikten sonra bu çok önemli görünmeyebilir, ancak ilk başta biraz kafa karıştırıcıydı, Ruby on Rails'i kullanmayı öğrenirken ve eminim birçok kişinin kafasını karıştırmıştır. diğerleri de. Phoenix sana endişelenecek bir şey daha veriyor.

Yönlendirmeyi yönetmek daha kolaydır.

Yönlendirme söz konusu olduğunda Phoenix ve Ruby on Rails çok benzer. Temel fark, bir isteğin işlenme şeklini nasıl kontrol edebileceğinizdir.

Ruby on Rails'de (ve diğer Rack uygulamalarında) bu, ara katman yazılımı aracılığıyla yapılırken Phoenix'te bu, "fişler" olarak adlandırılanlarla yapılır.

Fişler, bir bağlantıyı işlemek için kullandığınız şeydir.

Örneğin, Rails::Rack::Logger ara yazılımı, Phoenix'te Plug.Logger fişiyle yapılacak olan bir isteği Rails'de günlüğe kaydeder. Temel olarak Rack ara katman yazılımında yapabileceğiniz her şey fişler kullanılarak yapılabilir.

Phoenix'teki bir yönlendirici örneği:

 defmodule HelloWorld.Router do use HelloWorld.Web, :router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers end pipeline :api do plug :accepts, ["json"] end scope "/", HelloWorld do pipe_through :browser get "/", HelloController, :index end scope "/api", HelloWorld do pipe_through :api end end

Önce boru hatlarına bakalım.

Bunlar, isteğin içinden geçeceği fiş gruplarıdır. Bunu bir ara katman yazılımı yığını olarak düşünün. Bunlar örneğin isteğin HTML beklediğini doğrulamak, oturumu getirmek ve isteğin güvenli olduğundan emin olmak için kullanılabilir. Bunların hepsi kontrolöre ulaşmadan önce olur.

Birden fazla boru hattı belirleyebileceğiniz için, belirli güzergahlar için hangi fişlerin gerekli olduğunu seçebilir ve seçebilirsiniz. Örneğin yönlendiricimizde sayfalar (HTML) ve API (JSON) istekleri için farklı bir ardışık düzenimiz var.

Farklı istek türleri için tam olarak aynı ardışık düzeni kullanmak her zaman mantıklı değildir. Phoenix bize bu esnekliği veriyor.

Görünümler ve şablonlar iki farklı şeydir.

Phoenix'teki görünümler, Ruby on Rails'deki görünümlerle aynı değildir.

Phoenix'teki görünümler, şablonları oluşturmaktan ve şablonların ham verileri daha kolay kullanmasını sağlayan işlevler sağlamaktan sorumludur. Phoenix'teki bir görünüm, şablonun oluşturulmasının eklenmesiyle en çok Ruby on Rails'deki bir yardımcıya benzer.

“Merhaba Dünya!” yazan bir örnek yazalım. tarayıcıda.

Raylar üzerinde yakut:

app/controllers/hello_controller.rb:

 class HelloController < ApplicationController def index end end

app/views/merhaba/index.html.erb:

 <h1>Hello, World!</h1>

Anka kuşu:

web/controllers/hello_controller.ex:

 defmodule HelloWorld.HelloController do use HelloWorld.Web, :controller def index(conn, _params) do render conn, "index.html" end end

web/views/hello_view.ex:

 defmodule HelloWorld.HelloView do use HelloWorld.Web, :view end

web/şablonlar/merhaba/index.html.eex:

 <h1>Hello, World!</h1>

Bu örneklerin her ikisi de "Merhaba, Dünya!" tarayıcıda ancak bazı önemli farklılıklar var.

İlk olarak, Ruby on Rails'den farklı olarak Phoenix'te oluşturmak istediğiniz şablonu açıkça belirtmelisiniz.

Ardından, kontrolör ve şablon arasında duran Phoenix'te bir görünüm eklememiz gerekiyordu.

Şimdi, boşsa neden bir manzaraya ihtiyacımız olduğunu merak ediyor olabilirsiniz? Buradaki anahtar, kaputun altında Phoenix'in şablonu aşağıdaki koda kabaca eşit bir işlevde derlemesidir:

 defmodule HelloWorld.HelloView do use HelloWorld.Web, :view def render("index.html", _assigns) do raw("<h1>Hello, World!</h1>") end end

Şablonu silebilir ve yeni oluşturma işlevini kullanabilirsiniz ve aynı sonucu alırsınız. Bu, yalnızca metni veya hatta JSON'u döndürmek istediğinizde kullanışlıdır.

Modeller tam da budur: veri modelleri.

Phoenix'te modeller öncelikle veri doğrulamasını, şemasını, diğer modellerle ilişkilerini ve nasıl sunulduğunu ele alır.

Modelde şema belirtmek ilk başta garip gelebilir, ancak veritabanında kalıcı olmayan alanlar olan “sanal” alanları kolayca oluşturmanıza olanak tanır. Bir örneğe bakalım:

 defmodule HelloPhoenix.User do use HelloPhoenix.Web, :model schema "users" do field :name, :string field :email, :string field :password, :string, virtual: true field :password_hash, :string end end

Burada “users” tablosunda dört alan tanımlıyoruz: name, email, password ve password_hash.

Burada "sanal" olarak ayarlanan "şifre" alanı dışında pek ilginç bir şey yok.

Bu, değişiklikleri veritabanına kaydetmeden bu alanı ayarlayıp almamızı sağlar. Kullanışlı çünkü bu parolayı “password_hash” alanına kaydedeceğimiz ve ardından bunu veritabanına kaydedeceğimiz bir hash'e dönüştürmek için bir mantığımız olacaktı.

Yine de bir geçiş oluşturmanız gerekir; Modeldeki şema gereklidir çünkü alanlar Ruby on Rails'deki gibi modele otomatik olarak yüklenmez.

Phoenix ve Ruby on Rails arasındaki fark, modelin veritabanındaki kalıcılığı işlememesidir. Bu, aşağıdaki örnekte gösterildiği gibi, veritabanı bilgileriyle yapılandırılan “Repo” adlı bir modül tarafından gerçekleştirilir:

 config :my_app, Repo, adapter: Ecto.Adapters.Postgres, database: "ecto_simple", username: "postgres", password: "postgres", hostname: "localhost"

Bu kod, config/dev.exs veya config/test.exs gibi ortama özel yapılandırma dosyalarında bulunur. Bu, oluşturma ve güncelleme gibi veritabanı işlemlerini gerçekleştirmek için Repo'yu kullanmamıza izin verir.

 Repo.insert(%User{name: "John Smith", example: "[email protected]"}) do {:ok, user} -> # Insertion was successful {:error, changeset} -> # Insertion failed end

Bu, Phoenix'teki kontrolörlerde yaygın bir örnektir.

Bir Kullanıcıya bir ad ve bir e-posta sağlarız ve Repo, veritabanına yeni bir kayıt oluşturmaya çalışır. Daha sonra isteğe bağlı olarak başarılı veya başarısız girişimi örnekte gösterildiği gibi ele alabiliriz.

Bu kodu daha iyi anlamak için Elixir'de kalıp eşleştirmeyi anlamanız gerekir. İşlev tarafından döndürülen değer bir tanımlama grubudur. İşlev, iki değerden oluşan bir demet, bir durum ve ardından model veya bir değişiklik kümesi döndürür. Değişiklik kümesi, değişiklikleri izlemenin ve bir modeli doğrulamanın bir yoludur (değişiklik kümeleri sonraki bölümde ele alınacaktır).

Kullanıcıyı veritabanına eklemeye çalışan işlev tarafından döndürülen demetin modeliyle eşleşen yukarıdan aşağıya ilk demet, tanımlanan işlevini çalıştıracaktır.

Durum için bir atom yerine bir değişken ayarlayabilirdik (temelde Ruby'de bir sembol budur), ancak daha sonra hem başarılı hem de başarısız girişimleri eşleştirir ve her iki durum için de aynı işlevi kullanırdık. Hangi atomu eşleştirmek istediğimizi belirterek, o duruma özel bir fonksiyon tanımlarız.

Ruby on Rails, ActiveRecord aracılığıyla modele yerleşik kalıcılık işlevine sahiptir. Bu, modele daha fazla sorumluluk ekler ve bazen bir modelin test edilmesini sonuç olarak daha karmaşık hale getirebilir. Phoenix'te bu, kalıcılık mantığı ile her modelde mantıklı ve şişkinliği önleyecek şekilde ayrılmıştır.

Değişiklik kümeleri, net doğrulama ve dönüştürme kurallarına izin verir.

Ruby on Rails'de verilerin doğrulanması ve dönüştürülmesi, bulunması zor hataların kaynağı olabilir. Bunun nedeni, verilerin "before_create" ve doğrulamalar gibi geri aramalarla dönüştürüldüğünün hemen açık olmamasıdır.

Phoenix'te, bu doğrulamaları ve dönüşümleri değişiklik kümelerini kullanarak açıkça yaparsınız. Bu Phoenix'teki en sevdiğim özelliklerden biri.

Önceki modele bir tane ekleyerek bir değişiklik kümesine bakalım:

 defmodule HelloPhoenix.User do use HelloPhoenix.Web, :model schema "users" do field :name, :string field :email, :string field :password, :string, virtual: true field :password_hash, :string end def changeset(struct, params \\ %{}) do struct |> cast(params, [:name, :email, :password]) |> validate_required([:email, :password]) end end

Burada changeset iki şey yapar.

İlk olarak, Ruby on Rails'deki "strong_parameters"a benzer, izin verilen alanların beyaz listesi olan "cast" işlevini çağırır ve ardından "e-posta" ve "parola" alanlarının dahil edildiğini doğrulayarak "ad" alanını oluşturur. isteğe bağlı. Bu şekilde sadece izin verdiğiniz alanlar kullanıcılar tarafından değiştirilebilir.

Bu yaklaşımla ilgili güzel olan şey, tek bir değişiklik kümesiyle sınırlı olmamamızdır. Birden fazla değişiklik kümesi oluşturabiliriz. Kayıt için bir değişiklik seti ve kullanıcıyı güncellemek için bir değişiklik seti yaygındır. Belki de kullanıcıyı güncellerken değil, kayıt olurken sadece şifre alanını zorunlu kılmak istiyoruz.

Bu yaklaşımı Ruby on Rails'de yaygın olarak yapılanlarla karşılaştırın, doğrulamanın yalnızca "oluştur" üzerinde çalıştırılması gerektiğini belirtmeniz gerekir. Bu bazen Rails'de karmaşık bir modeliniz olduğunda kodunuzun ne yaptığını bulmayı zorlaştırır.

İçe aktarma işlevi basit, ancak esnektir.

“Ecto” adlı bir kitaplığın işlevselliğinin çoğu, modellere aktarılır. Modeller genellikle bu satırı en üstte bulunur:

 use HelloPhoenix.Web, :model

“HelloPhoenix.Web” modülü “web/web.ex” içinde bulunur. Modülde aşağıdaki gibi “model” adında bir fonksiyon bulunmalıdır:

 def model do quote do use Ecto.Schema import Ecto import Ecto.Changeset import Ecto.Query end end

Burada Ecto'dan hangi modülleri içe aktardığımızı görebilirsiniz. Burada istediğiniz diğer modülleri çıkarabilir veya ekleyebilirsiniz ve bunlar tüm modellere aktarılacaktır.

Sırasıyla görünümler ve denetleyiciler için aynı amaca hizmet eden “görünüm” ve “kontrolör” gibi benzer işlevler de vardır.

quote ve anahtar kelimeleri use kafa karıştırıcı görünebilir. Bu örnek için, bir alıntıyı, o işlevi çağıran modül bağlamında doğrudan o kodu çalıştırıyor olarak düşünebilirsiniz. Yani modülün içindeki kodun alıntının içine yazılmasıyla eşdeğer olacaktır.

use anahtar sözcüğü, kodu, çağrıldığı yerde çalıştırmanıza da olanak tanır. Esasen belirtilen modülü gerektirir, ardından onu çalıştıran modüldeki __using__ makrosunu, çağrıldığı yer bağlamında çağırır. Resmi kılavuzda alıntı ve kullanım hakkında daha fazla bilgi edinebilirsiniz.

Bu, belirli işlevlerin çerçevede nerede bulunduğunu anlamanıza gerçekten yardımcı olur ve çerçevenin çok fazla “sihir” yaptığı hissini azaltmaya yardımcı olur.

Eşzamanlılık esastır.

Eşzamanlılık Phoenix'te ücretsiz olarak gelir çünkü bu, Elixir'in ana özelliğidir. İş parçacığı güvenliği ve güvenilirliği konusunda herhangi bir endişe duymadan birden çok işlem oluşturabilen ve birden çok çekirdek üzerinde çalışabilen bir uygulamaya sahip olursunuz.

Elixir'de basitçe şu şekilde yeni bir süreç oluşturabilirsiniz:

 spawn fn -> 1 + 2 end

spawn sonra ve end ermeden önce her şey yeni bir süreçte işleyecektir.

Aslında Phoenix'teki her istek kendi sürecinde işlenir. Elixir, güvenilir ve verimli eşzamanlılık "Ücretsiz" sağlamak için Erlang VM'nin gücünü kullanır.

WebSockets'ın istemci ve sunucu arasında açık bir bağlantı sürdürmesi gerektiğinden (bu, uygulamanızı muhtemelen binlerce eşzamanlı bağlantıyı işleyebilmesi için oluşturmanız gerektiği anlamına gelir).

Bu gereksinimler, Ruby on Rails üzerine kurulu bir projeye çok fazla karmaşıklık katacaktır, ancak Phoenix bu gereksinimleri Elixir aracılığıyla ücretsiz olarak karşılayabilir.

Phoenix uygulamanızda WebSockets kullanmak istiyorsanız, Kanalları kullanmanız gerekecektir. Ruby on ActionCable eşdeğeridir, ancak ayrı bir sunucu çalıştırmanız gerekmediğinden kurulumu daha az karmaşıktır.

Phoenix, modern web uygulamaları oluşturmayı zahmetsiz hale getiriyor.

Büyük ölçüde farklılıklara odaklanmış olsak da, Phoenix'in Ruby on Rails ile bazı ortak noktaları var.

Phoenix, Ruby on Rails ile kabaca aynı MVC modelini takip eder, bu nedenle ana farkları bildiğinize göre, hangi kodun nereye gittiğini bulmak zor olmayacaktır. Phoenix ayrıca modeller, denetleyiciler, geçişler ve daha fazlasını oluşturmak için Ruby on Rails ile benzer oluşturuculara sahiptir.

Elixir'i öğrendikten sonra, Phoenix ile daha rahat olduğunuzda Ruby on Rails üretkenlik seviyelerine yavaş yavaş yaklaşacaksınız.

Ruby'de bir mücevher tarafından çözülen bir sorunla karşılaştığımda ve Elixir için benzer bir kitaplık bulamadığımda üretken olmadığımı hissettiğim birkaç zaman. Neyse ki, bu boşluklar büyüyen Elixir topluluğu tarafından yavaş yavaş dolduruluyor.

Phoenix'teki farklılıklar, karmaşık Ruby on Rails projelerinin yönetilmesinden kaynaklanan pek çok acının çözülmesine yardımcı olur. Tüm sorunları çözmeseler de sizi doğru yöne itmeye yardımcı olurlar. Verimlilik istediğiniz için yavaş bir çerçeve seçmek artık geçerli bir bahane değil, Phoenix her ikisine de sahip olmanızı sağlar.