Bir başlangıçta Rust'u kullanmak: Uyarıcı bir hikaye
Rust bazı şeyler için harikadır. Ancak hızlı hareket etmesi gereken bir girişim için onu seçmeden önce iki kez düşünün.
Bu yazıyı yazmakta tereddüt ettim, çünkü programlama dilleri üzerine kutsal bir savaş başlatmak ya da girmek istemiyorum. (Alev tuzağını ortadan kaldırmak için, Visual Basic şimdiye kadarki en iyi dildir!) Ancak birkaç kişi bana Rust deneyimimi ve projeleri için Rust'u alıp almamaları gerektiğini sordu. Bu nedenle, hızlı hareket etmenin ve ekipleri ölçeklendirmenin gerçekten önemli olduğu bir başlangıç ortamında Rust kullanmanın bazı artılarını ve eksilerini paylaşmak istiyorum.
Bazı konularda Rust hayranı olduğumu belirtmek isterim . Bu gönderi, Rust'ın bir dil olarak ne kadar kötü olduğu veya buna benzer bir şeyle ilgili değil. Bununla birlikte, bahsetmek istediğim şey, Rust kullanmanın, hızlı hareket etmeye çalışıyorsanız önemli bir faktör olabilecek önemsiz olmayan bir üretkenlik vuruşunu neredeyse kesinlikle nasıl içereceğidir. Şirketiniz ve ürününüz için hız etkisinin dilin faydalarına değip değmeyeceğini dikkatlice tartın.
Öncelikle , Rust'ın yapmak için tasarlandığı şeyde çok iyi olduğunu söylemeliyim ve eğer projeniz Rust'ın belirli avantajlarına ihtiyaç duyuyorsa (yüksek performanslı bir sistem dili, süper güçlü yazım, çöp toplamaya gerek yok, vb.) o zaman Rust harika bir seçimdir. Ancak Rust'ın genellikle pek uygun olmadığı durumlarda kullanıldığını ve takımların Rust'ın karmaşıklığının ve ek yükünün bedelini çok fazla fayda sağlamadan ödediğini düşünüyorum.
Rust ile ilgili birincil deneyimim, onunla önceki bir başlangıçta 2 yıldan biraz fazla çalışmaktan geliyor. Bu proje, aşağı yukarı geleneksel bir CRUD uygulaması olan bulut tabanlı bir SaaS ürünüydü: bir veritabanının önünde bir REST ve gRPC API uç noktası sağlayan bir dizi mikro hizmet ve diğer bazı arka- son mikro hizmetler (kendileri Rust ve Python'un bir kombinasyonunda uygulanmıştır). Rust, öncelikle şirketin birkaç kurucusunun Rust uzmanı olması nedeniyle kullanıldı. Zamanla ekibi önemli ölçüde büyüttük (mühendislik çalışan sayısını yaklaşık 10 kat artırdık) ve kod tabanının boyutu ve karmaşıklığı da önemli ölçüde arttı.
Ekip ve kod tabanı büyüdükçe, Rust'ı kullanmaya devam etmek için zamanla giderek daha ağır bir vergi ödediğimizi hissettim. Geliştirme bazen ağır ilerliyordu, yeni özellikleri kullanıma sunmak beklediğimden daha uzun sürdü ve ekip, Rust'ı kullanmaya yönelik bu erken karardan dolayı gerçek bir üretkenlik darbesi hissediyordu. Kodu başka bir dilde yeniden yazmak, uzun vadede geliştirmeyi çok daha çevik hale getirir ve teslim süresini hızlandırırdı, ancak büyük yeniden yazma işi için zaman bulmak son derece zor olurdu. Bu yüzden, kurşunu ısırmaya ve kodun büyük bir kısmını yeniden yazmaya karar vermedikçe, Rust'ta bir nevi sıkışıp kaldık.
Pasın dilimlenmiş ekmekten bu yana en iyi şey olması gerekiyordu, peki neden bizim için bu kadar iyi çalışmıyordu?
Rust'ın çok büyük bir öğrenme eğrisi var.
Kariyerim boyunca düzinelerce dilde çalıştım ve birkaç istisna dışında en modern, prosedürel diller (C++, Go, Python, Java, vb.) temel kavramları açısından çok benzer. Her dilin kendi farklılıkları vardır, ancak genellikle bu, diller arasında farklılık gösteren birkaç temel kalıbı öğrenme meselesidir ve ardından kişi oldukça hızlı bir şekilde üretken olabilir. Yine de Rust ile kişinin tamamen yeni fikirler öğrenmesi gerekiyor - yaşam süreleri, mülkiyet ve borç denetleyicisi gibi şeyler. Bunlar, diğer ortak dillerde çalışan çoğu insan için tanıdık kavramlar değildir ve deneyimli programcılar için bile oldukça dik bir öğrenme eğrisi vardır.
Bu "yeni" fikirlerden bazıları, elbette, diğer dillerde - özellikle işlevsel olanlarda - mevcuttur, ancak Rust bunları "ana akım" bir dil ortamına getirir ve bu nedenle, Rust'a yeni gelen birçok kişi için yeni olacaktır.
Birlikte çalıştığım en zeki ve en deneyimli geliştiricilerden biri olmama rağmen, ekipteki pek çok kişi (ben dahil) Rust'ta belirli şeyleri yapmanın standart yollarını, derleyiciden gelen genellikle gizemli hata mesajlarını nasıl çözeceğini veya anahtar kitaplıkların nasıl çalıştığı nasıl anlaşılır (aşağıda bununla ilgili daha fazla bilgi). Ekibin bilgi ve uzmanlığı paylaşmasına yardımcı olması için haftalık "Rust'u öğrenin" oturumları düzenlemeye başladık. Herkes yavaş gelişme hızını hissettiğinden, tüm bunlar ekibin üretkenliği ve morali üzerinde önemli bir yük oldu.
Bir yazılım ekibinde yeni bir dili benimsemenin nasıl göründüğüne ilişkin bir karşılaştırma noktası olarak, Google'daki ekiplerimden biri C++'tan Go'ya tamamen geçiş yapan ilk ekiplerden biriydi ve tüm ekibin tamamlanması yaklaşık iki haftadan fazla sürmedi. 15 küsur kişilik ekip ilk defa Go'da oldukça rahat kod yazıyordu. Rust ile, dilde her gün aylarca çalıştıktan sonra bile, ekipteki çoğu kişi kendini hiçbir zaman tam olarak yetkin hissetmedi. Bazı geliştiriciler, özelliklerinin ortaya çıkmasının beklediklerinden daha uzun sürdüğü ve Rust'a kafalarını sarmak için çok uzun zaman harcadıkları için sık sık utandıklarını söyledi.
Rust'ın çözmeye çalıştığı sorunları çözmenin başka yolları da var.
Yukarıda bahsedildiği gibi, oluşturduğumuz hizmet oldukça basit bir CRUD uygulamasıydı. Bu hizmette beklenen yük, bu belirli sistemin kullanım ömrü boyunca saniyede en fazla birkaç sorgudan fazla olmayacaktı. Hizmet, çalıştırılması saatler sürebilen oldukça ayrıntılı bir veri işleme hattının ön yüzüydü, bu nedenle hizmetin kendisinin bir performans darboğazı olması beklenmiyordu. Python gibi geleneksel bir dilin iyi performans sağlamada herhangi bir sorun yaşayacağına dair özel bir endişe yoktu. Web'e yönelik herhangi bir hizmetin üstesinden gelmesi gerekenin ötesinde özel bir güvenlik veya eşzamanlılık ihtiyacı yoktu. Rust'ı kullanmamızın tek nedeni, bu tür bir hizmet oluşturmak için özellikle uygun olduğu için değil, sistemin orijinal yazarlarının Rust uzmanları olmasıydı.
Rust, güvenliğin geliştirici üretkenliğinden daha önemli olduğuna karar verdi. Bu, birçok durumda - bir işletim sistemi çekirdeğinde kod oluşturmak veya belleği kısıtlı gömülü sistemler için - yapılacak doğru ödünleşimdir, ancak bunun her durumda doğru ödün olduğunu düşünmüyorum, özellikle hızın çok önemli olduğu başlangıçlarda değil. Ben bir pragmatistim. Takımdaki herkesin bu sorunlardan tamamen kaçınmak için tasarlanmış bir dil kullandığı için 4 kat üretkenlik isabetinden muzdarip olmasındansa, ekibimin ara sıra meydana gelen bellek sızıntısı veya örneğin Python veya Go'da yazılan kod için tür hatası ayıklamak için zaman harcamasını tercih ederim . .
Yukarıda belirttiğim gibi, Google'daki ekibim, tamamen Go'da bir hizmet oluşturdu ve zamanla 800 milyondan fazla kullanıcıyı destekledi ve zirvede Google Arama'nın QPS'sinin 4 katı gibi bir seviyeye ulaştı. Bu hizmeti inşa eden ve yürüten yıllarda Go'nun tip sistemi veya çöp toplayıcının neden olduğu bir sorunla kaç kez karşılaştığımızı bir yandan sayabilirim. Temel olarak, Rust'ın önlemek için tasarlandığı sorunlar başka yollarla çözülebilir — iyi test etme, iyi astarlama, iyi kod incelemesi ve iyi izleme. Tabii ki, tüm yazılım projelerinde bu lüks yoktur, bu yüzden Rust'ın diğer durumlarda iyi bir seçim olabileceğini tahmin edebiliyorum.
Rust geliştiricilerini işe almakta zorlanacaksınız.
Bu şirkette geçirdiğim süre boyunca tonlarca insanı işe aldık, ancak mühendislik ekibine katılan 60'tan fazla kişiden yalnızca iki veya üçü daha önce Rust deneyimine sahipti. Bu, Rust geliştiricilerini bulmaya çalışmak için değildi - sadece orada değiller. (Aynı şekilde, sadece Rust'ta kod yazmak isteyen insanları işe almakta tereddüt ettik , çünkü dil ve diğer teknoloji seçimlerinin çevik bir şekilde yapılması gereken bir başlangıç ortamında bunun kötü bir beklenti olduğunu düşünüyorum.) Rust geliştirici yeteneği, Rust daha yaygın hale geldikçe zamanla değişecektir, ancak Rust'ın riskli göründüğünü zaten bilen insanları işe alabileceğiniz varsayımına dayanarak.
Diğer bir ikincil faktör ise, Rust'u kullanmanın, ekipte Rust'ı bilen ve bilmeyenler arasında neredeyse kesinlikle bir ayrılığa yol açacağıdır. Bu hizmet için "ezoterik" bir programlama dili seçtiğimiz için, aksi takdirde özellik oluşturma, üretim sorunlarını giderme vb. Rust kod tabanının kuyrukları. Mühendislik ekibindeki bu değiştirilebilirlik eksikliği, hızlı hareket etmeye ve ekipteki herkesin birleşik güçlerinden yararlanmaya çalıştığınızda gerçek bir sorumluluk olabilir. Tecrübelerime göre, insanlar genellikle C++ ve Python gibi diller arasında geçiş yapmakta çok az zorluk çekiyorlar, ancak Rust yeterince yeni ve yeterince karmaşık, insanların birlikte çalışmasına engel teşkil ediyor.
Kitaplıklar ve belgeler olgunlaşmamış.
Bu, (umarım!) zamanla çözülecek bir sorundur, ancak örneğin Go ile karşılaştırıldığında, Rust'ın kitaplığı ve belgeleme ekosistemi inanılmaz derecede olgunlaşmamış. Artık Go, dünyaya yayınlanmadan önce Google'daki tüm özel bir ekip tarafından geliştirilmiş ve desteklenmiş olma avantajına sahipti, bu nedenle dokümanlar ve kitaplıklar oldukça cilalıydı. Rust, karşılaştırıldığında, uzun süredir devam eden bir çalışma gibi geldi. Pek çok popüler kitaplığın belgeleri oldukça seyrektir ve nasıl kullanılacağını anlamak için genellikle belirli bir kitaplığın kaynak kodunu okumak gerekir. Bu kötü.
Ekipteki Rust savunucuları genellikle "zaman uyumsuz/bekliyor" ve "evet, bu kitaplık için dokümanlar eksik" gibi şeyler söylerdi, ancak bu eksiklikler ekibi oldukça önemli ölçüde etkiledi. Hizmetimiz için web çerçevesi olarak Actix'i benimseyerek erkenden büyük bir hata yaptık; bu karar, kitaplığın derinliklerinde kimsenin nasıl düzelteceğimizi çözemediği hatalar ve sorunlarla karşılaştığımızda muazzam miktarda acı ve ıstıraba yol açtı. (Adil olmak gerekirse, bu birkaç yıl önceydi ve belki şimdiye kadar işler düzelmiştir.)
Tabii ki, bu tür olgunlaşmamışlık gerçekten Rust'a özgü değil, ancak ekibinizin ödemesi gereken bir vergi anlamına geliyor. Temel dil belgeleri ve öğreticiler ne kadar harika olursa olsun, kitaplıkları nasıl kullanacağınızı bilmiyorsanız, bunun pek bir önemi yoktur (elbette her şeyi sıfırdan yazmayı planlamıyorsanız).
Rust, yeni özelliklerin kabataslak çıkarılmasını çok zorlaştırıyor.
Başka kimseyi bilmiyorum, ama en azından benim için, yeni bir özellik oluştururken genellikle tüm veri türlerini, API'leri ve diğer ince ayrıntıları ön planda çalışmam. Çoğu zaman, bazı temel fikirlerin çalışmasını sağlamaya çalışırken ve işlerin nasıl çalışması gerektiğine dair varsayımlarımın aşağı yukarı doğru olup olmadığını kontrol etmeye çalışırken kod çıkartıyorum. Bunu örneğin Python'da yapmak son derece kolaydır, çünkü yazmak gibi şeylerle hızlı ve gevşek oynayabilir ve siz fikrinizi geliştirirken belirli kod yolları bozulursa endişelenmeyin. Daha sonra geri dönüp her şeyi düzene sokabilir, tüm tip hatalarını düzeltebilir ve tüm testleri yazabilirsiniz.
Rust'ta, bu tür bir "taslak kodlama" çok zordur, çünkü derleyici - açıkça tasarlandığı gibi - tip ve ömür denetimini geçemeyen her kahrolası şey hakkında şikayet edebilir ve edecektir . Bu, son, üretime hazır uygulamanızı oluşturmanız gerektiğinde çok mantıklıdır, ancak bir fikri test etmek veya temel bir temel oluşturmak için bir şeyi bir araya getirmeye çalıştığınızda kesinlikle berbattır. Makro unimplemented!
bir noktaya kadar yardımcı olur, ancak yine de siz derlemeye başlamadan önce her şeyin yığında yukarı ve aşağı tip denetimleri yapmasını gerektirir.
Asıl can sıkıcı olan şey, yük taşıyan bir arayüzün tip imzasını değiştirmeniz gerektiğinde ve tipin kullanıldığı her yeri değiştirmek için saatler harcarken kendinizi yalnızca bir şeye ilk hamlenizin mümkün olup olmadığını görmek için bulmanızdır. Ve sonra tekrar değiştirmeniz gerektiğini fark ettiğinizde tüm bu işi yeniden yapmak.
Rust hangi konuda iyidir?
Rust'ta kesinlikle sevdiğim şeyler var ve Rust'ta başka dillerde olmasını çok istediğim özellikler var. Sözdizimi match
harika. , Option
, Result
ve Error
özellikler gerçekten güçlüdür ve ?
işleç, hataları ele almanın zarif bir yoludur. Bu fikirlerin birçoğunun diğer dillerde karşılıkları vardır, ancak Rust'ın bunlara yaklaşımı özellikle zariftir.
Rust'ı, yüksek düzeyde performans ve güvenlik gerektiren ve hızla büyüyen tüm bir ekiple kodun ana bölümlerini hızla geliştirme ihtiyacı konusunda çok endişelenmediğim projeler için kesinlikle kullanırdım. Bireysel projeler veya çok küçük (örneğin 2-3 kişilik) ekipler için Rust muhtemelen gayet iyi olacaktır. Rust, performans ve güvenliğin çok önemli olduğu çekirdek modülleri, bellenim, oyun motorları vb. şeyler için ve sevkıyattan önce gerçekten kapsamlı testler yapmanın zor olabileceği durumlarda harika bir seçimdir.
Tamam, Hacker News okurlarının yarısını yeterince kızdırdığıma göre, sanırım sıradaki makalemin konusunu duyurmanın tam zamanı: Neden nano
üstün metin editörü. Bir dahaki sefere görüşürüz!