Swift’te enum dizmece
Swift’ciler olarak ozellikle MVVM, Rx, Reducers gibi mimariler yaygınlaştıkça enum kullanımını artırdık. Objective C’den gelen kavimler olarak pek alışkın olmasak da Swift’teki kullanım kolaylığı ve yetenekleri bize enum
’i sevdirdi. Dürüst olmak gerekirse Objective C’deki kullanımı daha samimiydi. Çünkü enum, enumeration’in kısaltılışı ve türkçede numaralandırma demek. Objective C’den gelen dedeler olarak biliyoruz ki her case
’in bir numarası vardir. Ancak Swift’teki liberallik sonucu görüyoruz ki bu yaklaşımın pek bir numarası yokmuş. İstersen bir case’i String
olarak ifade edebiliyorsun. İstersen direk kendisi ile de ifade edebilirsin.
Biz impossible state’leri, mesaj
, action
ve effect
leri enum
larla ifade ediyoruz dolayılısyla codebase’de enum
lar baya birinci sınıf vatandaş.
Bir de bunun küçük kardeşi var: switch
. guard let
case, if let
hayrani değilseniz switch
ile case
’leri yürüyeceksiniz, çare yok.
enum State<T, E: Error> {
case loaded(Result<T, E>)
case loading
}
Adı State
, generic T
parametresi aliyor ve iki case’i var, biri associated value’su olmayan loading
durumu, digeri ise Success tipi T
, hata tipi Error
protokolu olan loaded adında bir case
. Hem associated values’lu hem de generic parametreli.
Durum her zaman böyle olmuyor. Uygulamanız karmaşıksa çok özellikli ekranlarda genellikle şunun gibi enum
’larla çalışırsınız.
Bu gibi uzun listeleri alfabetik dizmek gayet yararli, nereye bakacaginizi biliyorsunuz, case’leri hizlica bulabiliyorsunuz, ayni zamanda bizim gibi kalabalik bir ekibiniz varsa ortak bir dilde buluşmuş oluyorsunuz. Her case eşittir ama aralarında kavga çıkmasın diye alfabetik sıralıyoruz. Bir de bu case’lerin uzerinde yuruyecek olan switch case’lerini hayal edin. Oradaki sikinti daha da büyük cunku her case’in altinda ilgili kod blogu da duruyor. Isler karmasiklasinca case’leri el ile sort etmek zorlaşıyor. Zaten çoğu zaman da hata yapıyoruz, PR çıkmışsak approval’lari kaybediyoruz, CI’i bekliyoruz vs.
Bu tip isleri yapmak icin SwiftFormat aracı var ancak henuz sortedCases
adinda bir rule yok (güzel fırsat!). Ben de oturdum, SwiftFormat olmadan bu isi nasıl yaparım diye biraz kafa yordum. Size bu yolculugumu anlatacağım.
Ilk once bir Automator tool’u yazdım. Tek bir ogesi var, Run Shell Script
. Orada da sort
komut satırı aracını kullandım. En iyi sonucu sort — ignore-leading-blanks -f
komutu verdi (Ayrıntılar icin $ man sort
). Ancak bu aracın yeteneği çok sınırlı, körlemesine sıralıyor, ve case let ve case ayrımını anlayamadığı icin tum case let
’leri grupluyor. Ayrıca switch
kod bloklarinda iyice saçmalıyor.
Ardından farkettim ki, iyi bir alfabetik case siralayici yazabilmem icin biraz daha alt seviyeye, compiler seviyesine inmem gerekecek. Swift derleyicisi bizim kaynak kodumuzu alip AST’ye ceviriyor, yani kodu anlamlandirmadan onceki ilk adim, tree
veri yapısına çevriliyor kaynak kodumuz. Şansıma da Apple SwiftSyntax adındaki aracı ile tam da bunu yapiyor ve bu arac GitHub’da acik kaynak kodlu olarak paylasiliyor. Bu araci kullanarak yapilmis su sitede ise canlı sekilde olusturulan AST’yi inceleyebilirsiniz.
Hemen yeni bir Swift paketi oluşturdum ve dependency olarak SwiftSyntax’i ekledim. Ardindan import SwiftSyntax
diyerek SwiftRewriter
class’ini inherit eden bir class actim, gerekli tokenlari manipule edecek olan metodlari override ettim. Boylece artik tokenize edilmis kaynak kodlari uzerinde modifikasyon yapabilir hale geldim.
SwiftSyntax öğrenirken, iyi bir parser nasıl yazılır konusu hakkında da gayet iyi iç görüler edindim, tavsiye ederim.
Kodu ne yazık ki paylasamayacagim ancak bahsetmemde bir kusur yok. Genel olarak kullandığım mantık su, amacım enum
ve switch case
’lerini alfabetik sıralamak olduğu icin case isimlerine ulaşmam gerekiyor (identifier token’i). Bunun icin EnumDeclSyntax
, SwitchStmtSyntax
gibi 4 adet token’in visit metodlarini override ettim ve ilgili tree
’leri traverse edip case’lerin identifier’larini sort edip sonucu tekrar standart output
’a yazdirdim.
Boylece Xcode içerisinde sort ettirmek istediğim kod blogunu seçip sag tıklayıp Services
’ten ilgili automator scriptini çağırmam yeterli oluyor. Basitçe bu script, seçtiğim metni standard input bekleyen komut satiri aracıma gönderiyor, program islemleri yapıp sonucu output buffer’ına yazıyor ve kodum IDE uzerinde update oluyor.
Referanslar
https://medium.com/@lucianoalmeida1/an-overview-of-swiftsyntax-cf1ae6d53494
Subscribe to my newsletter
Read articles from Erk Ekin directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by