Bu kılavuz, sürdürülmesi kolay olan bir kod yazmak için önerilen standartları içerir. Bu kurallara uyarak geliştiriciler okunaklılığı artırabilir, hataları azaltabilir ve işbirliğini kolaylaştırabilir. Standart hale getirilmiş bir kod stili hem şimdi hem de gelecekte proje üzerinde çalışan geliştiricilerin kodu anlamasını ve devam ettirmesini kolaylaştırmak için gereklidir.
Bu kılavuz öneriler sunar ancak son karar takımına aittir.
1. Yaygın Adlandırma Şekilleri
Adlandırma, okunabilir ve devam ettirilebilir bir kod için kritik öneme sahiptir. Kodunun her yerinde aynı adlandırma stilini devam ettirmeye çalış.
1.1 Yapılması Gerekenler
IsX: Genellikle bir soru soran mantık değişkenlerini adlandırmak için kullanılır (örneğin, IsEmpty).OnX: Çerçeve tarafından çağrılan aşırı yüklenilebilir bir fonksiyon.SubscribeX: Çoğunlukla bir OnX fonksiyonu geçirerek X adlı çerçeve olaya abone ol.MakeC: C oluşturucusunu aşırı yüklemeden C sınıfının bir örneğini oluştur.CreateC: Bir C sınıfı örneği oluştur ve mantıksal yaşam süresini başlat.DestroyC: Mantıksal yaşam süresini sonlandır.C:c: C sınıfının tek bir örneğiyle çalışıyorsan C adını vermek yeterlidir.
1.2 Yapma
Tür adlarını süsle.
Thing_typeveyathing_classyerine sadecethingyeterlidir.Numaralandırma değerlerini süsle.
color := enum{COLOR_Red, COLOR_Green}yerinecolor := enum{Red, Green}kullan.
2. Adlar
2.1 Türler lower_snake_case kullanır
Tür adları her zaman lower_snake_case olmalıdır. Bu kural tüm türleri içerir: yapılar, sınıflar, tür tanımları, özellikler/arayüzler, numaralandırmalar vb.
my_new_type := class2.2 Arayüzler sıfat olmalıdır
Arayüzler mümkün olan durumlarda yazdırılabilir, numaralandırılabilir gibi sıfatlar olmalıdır. Sıfatların doğru görünmediği durumlarda adın sonuna _interface ekleyebilirsin.
my_new_thing_interface := interface2.3 Diğer her şey PascalCase şeklindedir
Diğer tüm adlar ilk harfi büyük birleşik sözcüklerden oluşmalıdır. Modüller, üye değişkenleri, parametreler, yöntemler vb.
MyNewVariable:my_new_type = …2.4 Parametrik Türler
Parametrik türleri t veya thing olarak adlandır. Burada thing, türün neyi temsil etmesi gerektiğini açıklar. Örneğin:
Send(Payload:payload where payload:type)Burada parametre haline getirilmiş veriler olan, herhangi birpayloadtüründePayloadgönderiyorsun.Birden fazla parametrik tür varsa
t,u,ggibi tek harfler kullanmaktan kaçınmalısınHiçbir zaman
_tsonekini kullanma.
3. Biçimlendirme
Kod temelinin genelinde biçimlendirmenin tutarlı olmasını sağlamak önemlidir. Tutarlı bir kodun okunması ve anlaşılması hem senin için hem de diğer geliştiriciler için daha kolaydır. Proje için işe yarayan bir biçimlendirme stili seç.
Tutarlılığı sağlamanın bir örneği olarak aşağıdaki boşluk biçimlerinden birini seçebilir ve kod temelinin tamamında o biçimi kullanabilirsin:
MyVariable : int = 5
MyVariable:int = 53.1 Girinti
Girinti için dört boşluk kullan ve asla tab tuşunu kullanma.
Kod bloklarında süslü parantezler (parantezli) yerine girintili bloklar (boşluklu) kullanılmalıdır:
Versemy_class := class: Foo():void = Print("Hello World")option{a},my_class{A := b}vb. tek satırlı ifadeler yazılan durumlar dışında.
3.2 Boşluklar
Kodu bağlam için kısa tutmak anlamlı olmadıkça işleçlerin etrafında boşluk kullan. İşlemlerin sırasını açıkça tanımlamak için köşeli parantezler ekle.
VerseMyNumber := 4 + (2 * (a + b))Parantezlerin başına ve sonuna boşluk ekleme. Parantez içinde birden fazla ifade varsa tek boşlukla birbirinden ayrılmalıdır.
VerseMyEnum := enum{Red, Blue, Green} MyObject:my_class = my_class{X := 1, Y := 2} Vector := vector3{Left := 1000.0, Up := -1000.0, Forward := 0.0} Foo(Num:int, Str:[]char)Tanımlayıcı ve türü bir arada tut, atama
=işlecinin etrafına bir boşluk ekle. Tür tanımlarının ve sabit başlatma işleçlerinin (:=) etrafına bir boşluk ekle.VerseMyVariable:int = 5 MyVariable := 5 my_type := classParantezler, tanımlayıcılar ve fonksiyon imzalarının tür boşlukları için aynı önerileri takip et.
VerseFoo(X:t where t:subtype(class3)):tuple(t, int) = (X, X.Property) Foo(G(:t):void where t:type):void Const(X:t, :u where t:type, u:type):t = X
3.3 Satır Sonları
Satır sonu eklemek için boşluklu, çok satırlı bir biçim kullan.
Bunu Yap
VerseMyTransform := transform: Translation := vector3: Left := 100.0 Up := 200.0 Forward := 300.0 Rotation := rotation: Pitch := 0.0 Yaw := 0.0 Roll := 0.0Daha okunaklı ve düzenlenmesi kolay.
Bunu Yapma
VerseMyTransform := transform{Translation := vector3{Left := 100.0, Up := 200.0, Forward := 300.0}, Rotation := rotation{...}}Tek bir satırda okunması zor.
Numaralandırma başına yorum gerekiyorsa veya bir satır sonu ekleyeceksen numaralandırmaları boşluklu, çok satırlı biçimde tanımla.
Verseenum: Red, # Desc1 Blue, # Desc2
3.4 Ayraçlar
Devralmayan sınıf tanımları için parantez kullanma.
Bunu Yap | Verse |
Bunu Yapma | Verse |
3.5 Nokta-Boşluk Gösterimi Kullanma
Süslü parantez yerine nokta-boşluk “. ” gösterimini kullanmaktan kaçın. Bunu yapmak boşlukları ayrıştırmayı görsel açıdan zorlaştırır ve kafa karışıklığı yaratabilir.
Bunu Yapma | Verse |
Bunu Yapma | Verse |
4. Fonksiyonlar
4.1 Varsayılan olarak örtük dönüş
İşlevler son ifade değerlerini döndürür. Bunu bir örtük dönüş olarak kullan.
Sqr(X:int):int =
X * X # Implicit returnHerhangi bir açık dönüş kullanılıyorsa fonksiyondaki tüm dönüşler açık olmalıdır.
4.2 GetX fonksiyonları şöyle olmalıdır
Benzer semantiklere sahip olup geçerli değerler döndürmeyebilecek alıcılar veya fonksiyonlar <decides><transacts> olarak işaretlenmeli ve seçenek olmayan bir tür döndürmelidir. Çağıran işlev olası başarısızlığı işlemelidir.
GetX()<decides><transacts>:xBunun bir istisnası, koşulsuz olarak bir var değişkenine yazması gereken fonksiyonlardır. Başarısızlık değişikliği geri alır, bu nedenle dönüş türü olarak logic veya option kullanmayı gerektirir.
4.3 Tek Parametreli Fonksiyonlar Yerine Genişletme Metotlarını Tercih Et
Tek türlü parametresi olan bir fonksiyon yerine genişletme yöntemlerini kullan.
Bunu yapmak Intellisense'e yardımcı olur. Intellisense, Normalize(MyVector) yerine MyVector.Normalize() yazarak yazdığın metot adının her bir karakteriyle adlar önerebilir.
Bunu Yap | Verse |
Bunu Yapma | Verse |
5. Hata Kontrolleri
5.1 Tek satırlı Başarısız Olabilir İfade sayısını üç ile sınırla
Tek bir satırdaki koşullu kontrol/başarısız olabilir ifade sayısını en fazla üç ile sınırlı tut.
Verseif (Damage > 10, Player := FindRandomPlayer[], Player.GetFortCharacter[].IsAlive[]): EliminatePlayer(Player)Koşul sayısı üçten az olduğunda
()parantezliifbiçimini kullan.
Bunu Yap | Verse | Kodu kısa tutar ancak okunaklılığını korur. |
Bunu Yapma | Verse | Okunabilirliği iyileştirmeden kodu birden fazla satıra gereksiz biçimde böler. |
Her ifade için ikiden fazla sözcük kullanılıyorsa tek bir satırda çoğu zaman en fazla iki ifade daha okunaklıdır.
Verseif (Player := FindAlivePlayer[GetPlayspace().GetPlayers()], Team := FindEmptyTeam[GetPlayspace().GetTeamCollection().GetTeams()]): AddPlayerToTeam(Player, Team)Kuralı şu şekilde de uygulayabilirsin: Bir başarısızlık bağlamında tek bir satırda dokuzdan fazla sözcük kullanma. Limit aşıldığında boşluklu, çok satırlı biçimi kullan.
Bunu Yap | Verse | Metin daha iyi okunur ve bağlam birden fazla satırda anlaşılabilir. |
Bunu Yapma | Verse | Metnin ayrıştırılması zordur. |
Birden fazla başarısız olabilir koşulu tek bir
<decides>fonksiyonunda gruplandırmak kodun okunuşunu ve yeniden kullanılmasını daha kolay hale getirir. Kod yalnızca bir yerde kullanılacaksa geçici bir fonksiyonun olmadığı bir “bölüm” yorumu yeterli olabilir.Verseif: Player := FindRandomPlayer[] IsAlive[Player] not IsInvulnerable[Player] Character := Player.GetFortCharacter[] Character.GetHealth < 10 then: EliminatePlayer(Player)Şu şekilde yeniden yazılabilir:
VerseGetRandomPlayerToEliminate()<decides><transacts>:player= Player := FindRandomPlayer[] IsAlive[Player] not IsInvulnerable[Player] Character := Player.GetFortCharacter[] Character.GetHealth < 10 Player if (Player := GetRandomPlayerToEliminate[]): Eliminate(Player)Aynı kural
fordöngülerindeki ifadeler için de geçerlidir. Örneğin:Verseset Lights = for (ActorIndex -> TaggedActor : TaggedActors, LightDevice := customizable_light_device[TaggedActor], ShouldLightBeOn := LightsState[ActorIndex]): Logger.Print("Adding Light at index {ActorIndex} with State:{if (ShouldLightBeOn?) then "On" else "Off"}") if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() LightDeviceŞu şekilde daha iyi okunur:
Verseset Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] ShouldLightBeOn := LightsState[ActorIndex] do: if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() LightDevice
5.2 Bağımlı Hata İfadelerini Birlikte Gruplandır
Başarısızlık bağlamındaki bir koşul, başarılı olan daha önceki bir başarısızlık bağlamına bağımlı olduğunda mümkünse iki koşulu aynı başarısızlık bağlamında birlikte tut ve 5.1 numaralı kuralı izle.
Bunu yapmak kodun yerelliğini artırarak mantıksal anlayışı ve hata ayıklamayı kolaylaştırır.
Bunu Yap | Verse | Bağımlı veya ilgili koşullar gruplandırılır. |
Bunu Yap | Verse | Bağımlı veya ilgili koşullar gruplandırılır. |
Bunu Yapma | Verse | Gereksiz girintiler, akışı takip etmeyi zorlaştırabilir. |
Bunu Yapma | Verse | Gereksiz girintiler, akışı takip etmeyi zorlaştırabilir. |
Her bir potansiyel başarısızlığı (veya başarısızlık grubunu) ayrıca işliyorsan başarısızlık bağlamlarını bölebilirsin.
if (Player := FindPlayer[]):
if (Player.IsVulnerable[]?):
EliminatePlayer(Player)
else:
Print("Player is invulnerable, can’t eliminate.")
else:
Print("Can’t find player. This is a setup error.")6. Kapsülleme
6.1 Sınıflar Yerine Arayüzleri Tercih Et
Mantıklı olduğu durumlarda sınıflar yerine arayüzleri tercih et. Bunu yapmak uygulama bağımlılıklarını azaltır ve kullanıcıların çerçeve tarafından kullanılabilen uygulamalar sağlamasına izin verir.
6.2 Gizli Erişimi Tercih Et ve Kapsamı Kısıtla
Sınıf üyeleri çoğu durumda 'gizli' olmalıdır.
Sınıf ve modül metotları, uygun olduğunda <internal> veya <private> olacak şekilde, mümkün olduğunca kısıtlayıcı bir kapsama alınmalıdır.
7. Olaylar
7.1 Olayların Sonuna Event, İşleyicilerin Başına On Eki Getir
Abone olunabilir olaylar veya temsilci listesi adlarının sonuna ‘Event’, olay işleyici adlarının başına ise ‘On’ getirilmelidir.
MyDevice.JumpEvent.Subscribe(OnJump)8. Eşzamanlılık
8.1 Fonksiyonları Asenkron ile Süsleme
<suspends> fonksiyonlarını Async veya benzer terimlerle süslemekten kaçınmalısın.
Bunu Yap | Verse |
Bunu Yapma | Verse |
Dahili olarak bir şeyin gerçekleşmesini bekleyen bir <suspends> fonksiyonuna Await öneki getirilebilir.
Bu ön ek, bir API’ın nasıl kullanılması gerektiğini daha açık hale getirebilir.
AwaitGameEnd()<suspends>:void=
# Setup other things before awaiting game end…
GameEndEvent.Await()
OnBegin()<suspends>:void =
race:
RunGameLoop()
AwaitGameEnd()9. Öznitelikler
9.1 Öznitelikleri Ayır
Öznitelikleri ayrı bir satıra yerleştir. Özellikle öznitelikler aynı tanımlayıcıya eklenirse daha okunaklı olur.
Bunu Yap | Verse |
Bunu Yapma | Verse |
10. İçe Aktarma İfadeleri
10.1 İçe Aktarma İfadelerini Alfabetik Sıraya Koy
Örneğin:
using { /EpicGames.com/Temporary/Diagnostics }
using { /EpicGames.com/Temporary/SpatialMath }
using { /EpicGames.com/Temporary/UI }
using { /Fortnite.com/UI }
using { /Verse.org/Simulation }