Swift

Őszintén szólva szerintem is jól van így. Ugyanis felhívja a figyelmet egy lehetséges hibára. Ráadásul később (akár már 1-2 hónappal) olvashatatlan lesz így a kód, azaz nem tudjuk mi honnan van. Az egy dolog, hogy működnie kellene és ebből a szempontból igazad van, mégis azt mondom, hogy jó ez így.
Ráadásul! Ha egy másik fejlesztőnek eszébe jut, hogy “á, még A sor előtt le kellene futtatni valamit” és beteszi a kódját a “global” images elé, máris borult, hogy ki kivel van.
Ezek miatt sem értem, hogy miért hagyják el a self “előtagot” a programozók? Fáj kiírni vagy mert több helyet foglal?
Amúgy én megszüntetném a self nélküli hívásokat.

1 kedvelés

Elfogadom, hogy így gondoljátok, ebben is van logika. Egyébként én pl soha nem írom ki a self-et, csak ha muszáj (pl closure-ben) :D. Szerintem zavaró, és csak a helyet foglalja, feleslegesen nem írom le “kétszer” ugyanazt. Nem életszerű olyan kódot írni, amit self nélkül nehéz lenne értelmezni. (eltekintve pl a konstruktoron belüli értékadásnál stb)

Lényegében ugyanaz a helyzet a Swiftben is szerintem.

1 kedvelés

Ebben viszont egyetertek. A sok “self”, “this” inkabb csak zavaro. Celszerubb elkerulni az ugyanolyan nevu lokalis valtozokat. Szamomra az egyetlen elfogadthato kivetel, ahogy irtad is a konstruktor parameterei.

En is azt tamogatnam, hogy ki kelljen irni a self/thist mindenhova. Szamomra sokkal olvashatobb, ha mar ott akkor latom, hogy amit ott piszkalok az honnan jon. De elkepzelheto, hogy ez tenyleg megszokas kerdese, mert en ugy nottem fel, hogy ezek nem voltak opcionalisak.

1 kedvelés

Alapvetően 3+1 helyen lehet értelme kiírni:

  • setter/konstruktoron belül értékadásnál
  • ha a self/this-t mint paramétert kell átadni
  • konstruktoron belül hívni másik konstruktort
  • +1 javaban lehet statikus metódust hívni simán a nevével, vagy osztálynév+metódus formában. Itt zavaró lehet, hogy nem lehet “ránézésre eldönteni” melyik metódus statikus , melyik nem.
    De a Swiftben ugye ez is megoldott, mert kötelező kiírni az osztály/struct nevét előtte, tehát a self nem ad hozzá semmit a megérthetőséghez.
    Szerintem ha valaki betartja a konvenciókat, nem ír 100soros függvényeket, szépen tagolja a kódot, akkor nem fog olyan helyzetbe kerülni, hogy nem egyértelmű amit leírt. Én a Swiftlint-et használom, nálam bevált.

guard let self = self else { return } Ez meg külön vicces, hogy csak keyword, és nem csak, hogy valid kód, de hányszor futottam már bele, nem csak saját kódban. Amikor ezt kitalálták, hogy így jó lesz, gondolom akkor sem az érthetőség volt a fő szempont. :D

Ha egy ember ír egy kódot, akkor még talán elfogadom azt, hogy esetleg ne írjuk ki mindenhová. Bár ahogy írtam én is kiírom mindig, mert egyértelmű. Bár amúgy az xcode színezése is egyértelművé teszi. De!
Ahogy szóba került akár 100 soros blokk végén valaki használja a példány változóját self nélkül. Majd hónapokkal később eszébe jut, hogy a blokk elején ellenőrizni kellene valamit és ugyanezt a változónevet használja lokálisan. Onnantól kezdve fel is borult az egész és csak pislog, hogy milyen új hibák keletkeztek. (persze ehhez az kell, hogy a lokális változó típusa megegyezzen.)

Pl:

var images = [UIImage]()
func valami() {
    .... // akár 100 sorközben...
    let akarmi = images.map{...}
}

majd később hónapokkal.

func valami() {
    let images = masikImages.filter{...}
    .... // akár 100 sorközben...
    let akarmi = images.map{...}
}

És kész a probléma. És értem én, hogy oda kell figyelni és nem lesz gond, de így könnyne előjöhet a hiba. Nem beszélve arról, hogy ha többen is írják a kódot egyszerre, akkor lehet az egyik odafigyel ilyenekre, de ha a másik fél nem, akkor meg is történt a baj.

De amúgy meg akinek fáj kiírni azne írja ki, aki meg nem bír meglenni nélküle az írja ki. Nekem pont az fáj, ha nincs kiírva :D.
Az eredeti kérdésre reagálva még: én örülnék neki ha ilyen esetben figyelmeztetne engem az Xcode.

Nem hasznalunk olyan lokalis valtozot, ami elfed egy globalisat. (barmit ami feljebb mar definialva van.) Ez alol max az egy betus ciklusvaltozok lehetnek kivetelek, bar celszeruen azok sem.
Van annyi lehetoseg elnevezni dolgokat… Raadasul ha nem ugyanaz, akkor miert hivnam ugyanugy?

1 kedvelés

Arról nem is beszélve, hogy senki nem ír 100soros függvényt, de még 20 sorost sem. Ha ennél több sor valami akkor nagy valószínűséggel ott ki lehetne a dolgokat szervezni másik függvénybe, osztályba.
Egy tíz soros függvényben meg azért észreveszi az ember simán ha ilyet eset felmerül,hogy elfedi a lokális változó az osztály fieldjét.

Az évek során már láttam jónéhány kódot, amit másoktól vettem át. Vagy templateként árulják x összegért… megrendelő úgy gondolta, hogy így sokkal gyorsabb lesz a fejlesztés… hát nem.
Ha láttátok volna azokat a kódokat akkor értenétek a “félelmem”.
És ez a “változó probléma” csak a jéghegy csúcsa. Legutóbbi kódom tele volt olyan optional változókkal, amiket ! jellel unwrappoltak szinte mindenhol. Mivel az android programozó kényszerűségből szenvedett a kóddal. Aztán az adatbázis kapcsolat mind-mind a main loopon megy megfagyasztva ezzel az egész ui-t szinkronizálás alatt.
És még hosszan sorolhatnám. Tehát elhiszem, hogy aki tud programozni az betartja a szabályokat és minden tökéletes. De hát emberek írják a kódokat nem pedig agyonszabályzott gépek.

Najó, de ha valaki egyáltalán nem ért hozzá, az ne nyúljon a kódhoz.
“Tehát elhiszem, hogy aki tud programozni az betartja a szabályokat és minden tökéletes. De hát emberek írják a kódokat nem pedig agyonszabályzott gépek.”
Jó esetben mindenkinek be kell tartania a szabályokat, konvenciókat, különben az eredmény olyan is lesz. Az nem mentség a gányolásra, hogy nem ért hozzá. Mondjuk a projektvezető hibája is, hogy olyan feladatot ad ki amihez a kolléga egyáltalán nem ért. De miután összegányolta, utána valakinek ki kell javítania az egészet, és dupla annyi pénz és idő megy el a dologra.

Persze, alomvilag mindenkitol elvarni ezt. De inkabb arra probalok kilyukadni, hogy en betartom, illetve az igenyes programozok betartjak. Ennyi.
Ezek utan ujra ranezek a nagyon sok penzert sok konzultans altal odahanyt 25000 soros osztalyra, amiben az utolso 6000 sor egy dummy metodus ami azert van csak ott, hogy meglegyen a 75% code coverage, mert akkora gany, hogy nem igazan lehett ra tesztet irni. Ha lett volna ra eselyem, ezt ugy dobom vissza, hogy nezni is szep. Nem volt. Ez van. Kontarok vannak. Es rajtuk az se segit, ha mindenhova kiirjak, hogy self/this.
De attol a sajat munkankban legyunk igenyesek.

1 kedvelés

Totál egyetértek!

Emlékszem, mikor bemutatták a Swiftet vagy rá egy évre az egyik WWDC előadáson el is hangzott valami ilyesmi, hogy a ! unwrap lehetőség nem azért van, hogy kielégítsük a swift igényeit és ne dobjon error-t vagy warningot.

Hivatalosan is megjelent a Swift 5. Itt vannak a változtatások: Swift 5 Release Notes for Xcode 10.2 | Apple Developer Documentation

Érdekes, az egyik változtatás kicsit hasonlít arra amiről beszéltünk:

Létre lehet hozni saját típusokat olyan névvel, mint amik már gyári típusoké. Ekkor az eredetit a Swift. prefixszel lehet elérni.
Erre mondjuk szerintem nem volt szükség.

Xcode frissítés szükséges hozzá.

1 kedvelés

os és azon belül az os_log használja valaki?
Mert most szeretném elkezdeni használni, de nem egyértelműek a dolgok.
Főleg az nem, hogy alapból az OSLogType .debug típussal jelölik meg egy kód sort, akkor az a release-ben is benne marad? Ha nem akkor melyik level marad benne?

Valamint milyen technikák vannak arra, hogy egy-egy logot elrejtsek anélkül, hogy kikommentelném a log sort? Mert most preprocessor macroval oldom meg, hogy csak akkor keletkezzen log, amikor akarom.
Érdemes külön logger osztályt csinálnom, amiben ilyen dolgokat lekezelek?

Konkrétan az OSLog-ot nem használom, én a SwiftyBeaver-t lib-et szoktam, de ahogy látom van sok hasonlóság.
Az OSLog előnye, hogy a Console appban ki tudod olvasni az apphoz tartozó logot.
A .debug “típusnak” nincs köze ahhoz, hogy releaseben is benne marad e, ezek a típusok: error, info, debug, stb csak annyit jelentenek, hogy más “kategóriába” kerül a log, könnyebb keresni, csoportosítani.
Pl a SwiftyBeaver is színezi a logot attól függően milyen típusú, így könnyű keresni.

Ezt az elrejtés dolgot nem nagyon értem, annál egyszerűbb nincs ha kikommenteled, de szerintem olyat is csinálhatsz, hogy csinálsz még egy targetet ami mondjuk a development, és akkor az alatt mindig kiíródnak a release alatt nem, bár a lognak mondjuk pont az a lényege, hogy mindig kiírja az adott dolgot.

A rettenetesen sok log megnehezíti a kód debuggolását később. Van olyan, amikor egy adott területet szeretnek debuggolni. Ilyenkor ezt a preprocessort bekapcsolom, és másikat ki. Ha meg már ennek a debug sorai sem kellenek, akkor ezt is kikapcsolom.

Persze tudom, hogy létre lehet hozni custom OSLogType típust és ezzel meg könnyebb leszűkíteni a logot. Ha ez működne, akkor nem kellene preprocessoroznom. Viszont semmikép sem szeretném, ha benne maradnának a kiadásban ezek a logok.

Az OSLog nem annyira “egyszerű”, mert figyelembe veszi a privacyt.

De a memory vs data store ami miatt nem értem a pontosan működést. Persze lehet csak annyi, hogy ki kell tesztelnem. Bemásoltam ide pár érdekes részét a dokumentációból.

Ja és igen, a dokumentáció kifejezetten írja, hogy a debug típusú logoknak nem ajánlott megjelennie a kiadott szoftverben. Hogy ez jó-e vagy sem, az már más kérdés.

Privacy
The unified logging system considers dynamic strings and complex dynamic objects to be private, and does not collect them automatically. To ensure the privacy of users, it is recommended that log messages consist strictly of static strings and numbers. In situations where it is necessary to capture a dynamic string, you may explicitly declare the string public using the keyword public . For example, %{public}s .

Info-level messages are initially stored in memory buffers. Without a configuration change, they are not moved to the data store and are purged as memory buffers fill. …

Debug-level messages are only captured in memory when debug logging is enabled through a configuration change. They’re purged in accordance with the configuration’s persistence setting. Messages logged at this level contain information that may be useful during development or while troubleshooting a specific problem. Debug logging is intended for use in a development environment and not in shipping software.

Ha a CALayerből csinálok egy subclass-t és szeretném használni a Codable protokollt, azt hogyan tehetem meg? Mert az alap osztály az csak az NSCoding-ot használja.
A nehézség az, hogy valahogy tudnom kellene az alap osztály tulajdonságait “menteni illetve betölteni”. Az egyetlen egy ami eszembe jut, hogy az init(from decoder: Decoder) és az encode(to encoder: Encoder) funkcióban NSKeyedArchiver és NSKeyedUnarchiver segítségével menteném el és tölteném be a super class állapotát. Van valami jobb ötlet?

Hátha valaki tudja a választ! :slight_smile: Hogyan tudnám a property wrapper változókat egy tömbbe tenni? A property wrapper osztályom generic, mivel bármilyen érték lehet mögötte (szó szerint bármi). Viszont az összes típus kötelezően egy (nem generic) protocolból származik. Viszont én mindenképpen szeretném magát a property wrapper értékeket tömbként látni, mert van, hogy 40-50 ugyanolyan property wrapper változó van egy osztályon belül és nem szeretném leírni őket számtalanszor:

Lehet, hogy hülyeség, de Swiftben nincs enum?

Nem hülyeség, sőt, a változók mögött az mind enum. :) Csak ebből nem derül ki. :) Az SVGFliterEffect … az mind-mind egy-egy enum típusa.

Egyébként ez a property wrapper elég új dolog. a SwiftUI-jal mutatták be, de akkor még mint ha nem lett volna elérhető a swiftben, csak egy évvel később. A lényege az, hogy van egy bármilyen típusú objektumod, és amögött elrejtve a háttérben egy másik típus, ami a működésérét felel. Erre kér jó példát szoktak írni, az egyik amikor a háttérben a userpreferencesbe/ből mented/olvasod be az adatokat, a másik pedig, amikor mondjuk egy int-nek a háttérben minimum és maximum értéket adsz meg.

Egyébként ennek most nyilván az az értelme, hogy az enum típusoknál én már a konkrét stringből kiértékelt értékeket tárolom. Pl. color esetében már magát az UIColor.black konkrét színt. Míg amikor majd el akarom menteni, akkor string-re kell konvertálnom. Tehát a StringStorable valójában az enum string megfelelője. Amikor megváltoztatom az enum értéket, akkor a háttérben a StringStorable-nél azonnal átalakítom stringre is ott úgy tárolom. Ha svg-t kellene menteni, és akkor kellene átkonvertálnom akár több ezer ilyen elemet stringként, akkor az nagyon lassú lenne, míg így csak le kell kérdezni a jelenlegi értéket.

Nyilván megoldható lenne, hogy mindegyeket egy struct “belsejébe” teszem és hasonlóan működhetne, annyi különbséggel, hogy mondjuk fillColor helyett fillColor.instance vagy valami hasonló néven kellene hivatkoznom rá. De amúgy maga a property wrapper is hasonlóan működik a háttérben.