Sintaksa za provjeru strukture objekta

Kako vam se dopada?
Vidite li svrhu? :slight_smile:

			BASIC types:

				string 			- string
				int 			- integer
				float 			- float
				numeric_int 	- numeric int 		//što znači da je ok ako je broj u string formatu
				numeric_float 	- numeric float 	//što znači da je ok ako je broj u string formatu
				numeric 		- numeric 			//broj može biti u string formatu
				array 			- array
				object 			- object
				aobject 		- array ili object
				bool 			- boolean koji uključuje i 1 i 0 ..ili zadano stringom: "true" / "false"
				booleaen 		- boolean koji se odnosi samo na true i false
				null 			- null 
				* - wildcard 	- any type

			MORE spec types:
				email 			- string koji je email
				url 			- string koji je url
				username 		- string koji je username
				password 		- string koji je password
				password1 		- string koji je password minimalno težine 1
				password2 		- string koji je password minimalno težine 2
				password5 		- string koji je password minimalno težine 5
				//..typeovi su extendabilni, ali nativno bi funkcija trebala podržavati velik spektar specijalnih typeova

			OR statements:
				array|object 		- array ili object
				string|int|array 	- string ili integer ili array  //ILI statement se može kaskadno nizati koliko god treba

			NESTED statement:
				array<int> 			- array koji sadrži isključivo integere
				array<string> 		- array koji sadrži isključivo stringove
				array<url> 			- array koji sadrži isključivo url-ove
				array<url|int> 		- array koji sadrži isključivo url-ove ili integere
				array<array<int>> 	- array koji sadrži isključivo arraye-ove koji sadrže integere

			LENGTH statements:
				array(4) 		- array koji sadrži isključivo 4 elementa
				array(>4) 		- array koji sadrži više od 4 elementa
				array(<4) 		- array koji sadrži manje od 4 elementa
				array(>=4) 		- array koji sadrži 4 ili više elementa
				array(<=4)  	- array koji sadrži 4 ili manje elemenata
				array(>=4<10) 	- array koji sadrži 4 ili više elemenata i manje od 10 elemenata
				array(4-10) 	- array koji sadrži od 4-10 elemenata. Uključujući 4 i 10.

				object(>4) 		- objekt koji ima više od 4 ključa
				string(>4) 		- string duži od 4 karaktera
				int(>4)			- integer veći od 4
				numric(>4)		- bilo koji numeric veći od 4

				//za object i aobject vrijede isti LENGTH statementi, samo se odnose na količinu ključeva koje objekt posjeduje
				//za string tipove također vrijede LENGTH statementi, tako je moguće zadati npr: password(>7)
				//za numeric tipove, length provjerava dali iznos broja spada u zadani range

			COMBINE NESTED and LENGTH

				array(4)<int> -> array koji sadrži isključivo integere, i točno 4 elementa
				array?(4)<int> -> array koji sadrži isključivo integere, i točno 4 elementa ..ili je null  //validno je pisati i na način sa upitnikom na kraju: "array(4)<int>?""

			EXACT TYPES statements:

				array[string,int,string|int,*] 							- array koji sadrži 4 elementa, redom: 1:string, 2:integer,  3:string ili integer, 4: any type
				object[key1:*, key2, key3:string, -key4, -key5:int]  	- object koji mora sadržavati key1 bilo kojeg tipa i key2 također bilo kojeg tipa, zatim ne smije imati ključ key4 i ne smije imati ključ key5 koji je integer
				object[key1.key2:int] 									- object koji mora sadržavati int type na svojoj putanji: object.key1.key2 


			COMBINE EXACT WITH LENGTH:

				object[key1:string](1) - objekt koji mora sadržavati ključ key1 koji je string i koji ukupno mora sadržavati 1 ključ. 

			EXACT VALUES statements:
				int[1]      - integer koji je 1
				int[2]      - integer koji je 2
				int[2|3]    - integer koji je 2 ili 3  
				string[ivo] - string koji je ivo
				string[ivo|ana] - string koji je ivo ili ana. Za string se ne smiju pisati specijalni znakovi, tipa: "()[]<>|""
			
			NULL is accepted statement:

				string? - string koji može biti i null, ekvivalent tipu: string|null
				int? - ekvivalent tipu int|null 
				int[1]? - ekvivalent tipu int[1]|null ili int?[1]
				...itd.

			CONTROL RESPONSE

				a:int|b:string     									-> Za slučaj da je provjeravani objekt integer, fukcija vraća: {a:true}
				this_is_integer:int|this_is_string:string     		-> Za slučaj da je provjeravani objekt integer, fukcija vraća: {this_is_integer:true}
				a:array<b:int|c:string>|d:array<e:bool|f:float> 	-> Za objekt [1,1] funkcija vraća: {a:true, b:true}
																	-> Za objekt [1,"string"] funkcija vraća: {a:true, b:true}  //iako array sadržava i string, ali provjera se kod ili statementa prekida nakon prvog ispunjenog uvjeta
																	-> Za objekt [4.2] funkcija vraća: {d:true, f:true}  		//iako array sadržava i string, ali provjera se kod ili statementa prekida nakon prvog ispunjenog uvjeta
																	-> Za ulaz "string" vraća {a:false}
																	
				array<a:int|b:string>								-> Za ulaz "string" vraća -> false

 				//forsiranje control reponse-a
				:array<a:int|b:string> 								-> Za objekt koji je string bi inače vratilo false. (Jer provjera nebi niti stigla unutar arraya koji ne postoji)
																		tako da u ovom slučaju da bi forsirali control response, moramo zakačiti bilo koji key: na početak izraza ...ili je dovoljno dodati i samo dvotočku.

				//ključevi za kontroliranje responsa moraju spadati u skup karaktera: \w

			ADDING CUSTOM TYPES

				addCustomControlType("strlen4", function(x){return isString(x) && x.length==4});
				array<strlen4>  -> za ulaz ["abcd", "efgh"]  -> vraća true

Apsolutno ne, jer nemam pojma sta si htio reci.

A uz sve to nigdje ne vidim neki objekat ovdje :grinning:
Dobro bi doslo neko obrazlozenje.

Ok, mislio sam da je možda auto-explained kroz sintaksu :slight_smile:

…a nema nikakvog objekta, jer nema niti konkretnih primjera poziva. Mada sve su to gore različiti primjeri, skoro isto kao da su napisani pozivi, zato jer je poziv isti vrag, npr:

var objekt = [1,2,3];
var r = controlType("array<int>", objekt ); // r = true;
var r2 = controlType("array<string>", objekt ); // r2 = false;

Uglavnom, ovisno o potrebi i želji može se testirati struktura nekog objekta.

Primjena…pa može biti razna.
Glavna zamisao mi je bila da se može jednostavno testirati struktura primljenih podataka na nekom API-servisu, i da onome tko koristi servis možeš vratiti automatizirani odgovor što je krivo poslao. (Bogat response-log se kreira unutar metode, tako da nije potrebno praktički ništa raditi osim prosljediti taj odgovor kod greške)
Tako da sa ovim alatićom se za takve stvari ne mora pisati nikakav suvišan code…a trebao bi bit bogat mogućnostima kako se sve može testirati struktura primljenih inputa (I bit će mogućnosti još dosta…ali ovo gore je fina osnova.)

Osim API-a, svaka kompleksnija funkcija se može dodatno kontrolirati sa ovime…da se lakše uoči ako nailazi neželjeni “uljez”.

Osim toga, može se praviti nešto što se u C#-u zove function ili input signature. Ideja je da funkcija lako prepoznaje strukturu inputa i da različito reagira za različite strukture inputa. Recimo za primjer funkcija getUserComments() može primati dva različita tipa parametra:

getUserComments(userID)  //1. userID je string
getUserComments(user)    //2. user je objekt/klasa koja predstavlja usera

Takve jednostavne stvari nije nikakav problem sa jednim if-om detektirati i odreagirati prema tipu inputa. Ali, vrlo brzo se to zakomplicira ako se takve stvari riješavaju sa if-ovima. A metoda koja može bogato testirati strukturu objekta, je odličan alat da se to rješi simpatično i pregledno bez petljanja sa code-om.

Dalje, ovo je fina podloga da se to automatizira i na razini compilera. Znači napravi se js-loader koji će se koristiti gornjom sintaksom i onda se već može ići u smjeru automatiziranja klasa …i onoga što radi typescript. (Samo meni typescript ograničenja u C#-u nikako nisu legla, te mislim da je ovo jedan bogatiji način da se opiše struktura objekta)

Dalje od toga su mogućnosti razne…jednom kada opišeš neki objekt sintaksom koja opisuje njegovu strukturu, onda imaš mogućnost i automatizirati izradu dokumentacije za takve opisane objekte, ili ti ga za neke “pointe” kroz koje prolazi cijeli skup objekata.

I to će mi biti sljedeći korak. Dodati u js-loader da prepoznaje ovu sintaksu kada na nju naiđe i da automatski kreira dokumentaciju i puca ju negdje na server. Što je jako cool, jer kod takvog načina generiranja dokumentacije imaš mogućnost da tone i tone dokumentacije ažuriraš u neki bolji “stil”, samo tako što unaprijediš kompajler koji pravi dokumentaciju. Ako ručno hardkodiraš dokumentaciju, teško se boriti sa lošom prošlošću…nakon što shvatiš da se nešto trebalo praviti na bolji način…

Druga naravno velika prednost, ovako ubijaš jednim udarcem dvije muhe. Ovako pišeš samo code koji ima neku svoju svrhu …a online dokumentaciju dobivaš “gratis”, ili ti ga automatizirano.

P.S. da bi se gornja sintaska mogla primjeniti i u svrhu dokumentacije…treba vrlo malo toga dodati. Treba samo omogućiti gdje će dolaziti komentari određenog attributa…a to nije problem. Glavno da kompajler koji će obrađivati tu sintasku, da može razumjeti strukturu opisanog objekta i da to može kvalitetno posložiti onda u nekakav dokument.

I bilo bi čudno kada se nebi spomenuo i normJS, tako da valja spomenuti da će po normativu normJS-a, sve komponente morati moći razumno odreagirati ako prime krivi/neočekivani input, što će činiti upravo pomoću ovakve komponente.

Ne znam, ali ja licno ne vidim nista revoluctionarno u ovome, cak sta vise mislim da svaki iole ozbiljniji framework ima nacin da prokrije ovo.
Dobra dokumentacija API-a i ispravni status code-ovi su meni i vise nego dovoljni.

Funkcija treba biti sto manje kompleksna :slight_smile: A pored toga ne vidim nista novo ovdje, TS i Flow rade vec tu stvar tj. njihov compiler.

Kakva to ogranicenja TS ima, koja su tebi stvarala probleme ?

Swagger UI

Kada se sve sabere i oduzme ja iskreno ovdje ne vidim nista toliko revolucionarno i zbog cega bi se trebao pisati neki novi compiler, standard ili sta vec.
Probaj me razuvjeriti, ako sam u krivu :slight_smile:

Da, ali cilj je automatizirati i kreiranje te dokumentacije i vraćanje status codova. Ako se to radi pješice…onda je puno teže.

Kompleksne stvari primaju i kompleksne konfiguracijske/input parametre. Od toga se ne može pobjeći. Možeš kompleksnu stvar rasčlaniti na puno jednostavnih cjelina…no to ne znači da na nekoj razini iznad svih tih slojeva neće biti “point” kroz koji prolazi složena struktura podataka.

Ovdje je bio cilj da se stvori razina ispod toga što rade ti kompajleri. Tako da onaj tko koristi ovu sintaksu, da je neovisan hoće li od toga raditi kompajler…ili će istu metodu koristiti u run-time modu za provjeru nečega.
Znači, upravo razbijanje viših slojeva na niže

…čime se diže razina fleksibilnosti načina primjene.

Ne znam točno za TS, ali znam za C# …a u pozadini je ista ekipa ako se ne varam, pa je moguće da su ograničenja ista.
Uglavnom, u C# je alias za sve tipove podataka “object”, jer polaze od toga da je sve objekt. U mojoj gore sintaksi je to “*” … i sad recimo, kod mene će bilo koji tip arraya proći kroz filter:

array<*>
Kod njih ako napišeš array, kroz to ti neće proći array stringova. Nego moraš baš napisati
“object” …što onda pušta i array stringova, ali isto tako pušta bilo koga drugoga, jer je sve objekt.
Nadalje, kod njih ako je array …ona unutra mora biti samo array booleanova…ne možeš taj array više miksati sa ničim. To je dobro u teoriji…u praksi ponekada najelegantnije rješenje želi prekršiti tu praksu…i oni su tu jako nefleksibilni.
Kako cijelu priču tjeraju na razini kompajlera…onda ponekada zna biti baš mutavo tražiti načine da se nešto složi što bi u suprotnom bilo “pjesma”.
Ali da ne duljim, jer o C#-u bi mogao napisati toliko hejta…i budem jednog dana. Za taj jezik samtram da je smeće nad smećima.
Naravno, on mi je pokazao i neke lijepe pristupe programiranju, koje ću ponesti dalje sa sobom. O nekim od tih pristupa sam razmišljao i prije nego sam se sreo sa C#, ali se nisam usudio petljati u tom smjeru. Sada kada sam vidio da su i oni radili ono o čem sam razmišljao…dalo mi je to jednu finu potvrdu da sam bio na dobrom tragu.
No njihova rješenja mojih zamisli mi se nikako ne dopadaju… …dovoljno je reći da su ga toliko zakomplicirali da traje 20-30 sekundi refresh stranice kada razvijaš backend web-a u C# …i to je pametnom dosta koliko su daleko zašli u slijepu ulicu. Za TS se iskreno nadam da ne trpi iste/slične probleme…ali ja ga vjerovatno neću niti probati nakon iskustva sa C#.

Ne kažem da takvih rješenja već ne postoji. Meni je dosad praksa pokazala da za takve alate je najbolje imati in-house rješenje. Daleko veća fleksibilnost nauštrb brzine početnog napretka…ali na dulje staze veliki plus.Što ne znači da ne valja pročačkati i druge alate i pokupiti ono što je dobro kod njih. (I koristiti ih dok ne dođe prilika za razvoj in-house rješenja)

Ali ovdje nije primarno riječ o takvom alatu… nego o sintaksi za kontroliranje strukture objekta.
Čak se ne priča niti o algoritmu koji pokreće tu sintaksu…nego samo o sintaksi i mogućnosti kontrole neke strukture.
Isto kao što imaš SQL sintaksu…nebitno ti je koji ju engine vrti dok ju izvršava pravilno i naravno, optimizirano. Ono što ti je bitno, bitno ti je da ta SQL sintaksa pokriva sve tvoje potrebe dohvata podataka iz baze.

Tako i ovdje, poanta je na sintaksi i mogućnostima testiranja neke strukture. Koji će je engine pokretati…skoro pa nebitno.

U tom smislu treba shvatiti da iako se ovaj proces testiranja “typescript” dešava na raznim razinama…da nema uopćene sintakse koja je data “malom čovjeku” u tu svrhu. A normJS radi upravo to…izvlači takve “nevidljive” djelove kodiranja i stavlja fokus na njih. Samim tim fokusom se može pojaviti i norma oko takvih stvari. (Unutar normJS-a će sigurno biti normativ…ali prave norme uzmu svoj zamah i na širem spektru…same od sebe…jer se šire ko “zaraza” ako su dobro konceptirane u startu :slight_smile: )

I zato mi je bitno da je koncept dobar, potpun i praktičan za pisanje.

Ti si prvo spomenuo da ne vidiš svrhu, a onda si i sam nabrojao hrpu različitih mjesta gdje se isto koristi. Kako onda nema svrhu, ako se već koristi?

Možda si onda mislio zapravo: “Nema svrhu još jedna ovakva sintaksa u nizu…”. Jer očito da imaju svoju svrhu, kada već postoje primjene ovog tipa.

A čuj, u svijetu uvijek ima prostora za još jednoga. :smiley: :smiley:
…a što se tiče konkretnog problema, zaista nisam primjetio da postoji ikakva uopćena sintaksa na ovom polju, kao što recimo postoji JSON sintaksa za serializaciju, ili SQL za query-e prema bazi…ili regex sintaksa za testiranje strukture stringa…itd.

Ako postoji neka šire prihvaćena sintaksa na ovom polju za testiranje strukture objekta, koja pokriva bogatu mogućnost testiranja strukture…molio bih dokumentaciju na tu sintaksu. :slight_smile:

Necemo sad filozofirati :smiley: Ako se vodimo tom logikom zasto svi onda ne pisemo funkcije od 200 linija koda ? Ogromne i kompleksne funkcije narusavaju mnogo principa clean code-a, i naravno da ih treba razbiti u manje funkcije ili cak mozda u klasu u zavisnosti od toga sta ta funkcija radi.

Jesi cuo mozda za pojam generics ? :smiley:

Mozda nesto kao json schema?
https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1

1 Like

I naravno, primam prijedloge oko same sintakse i njenih mogućnosti što bi trebala pokrivati.

Ja sam recimo primjetio da bi bilo zdravije za provjeru duljina struktura da se piše:

array{4} …umjesto array(4) …jer obične zagrade će biti pametnije iskoristtii za povezivanje i/ili statementa.

…u tom smjeru, kako bi sintaksa trebala izgledati i što bi sve trebala pokrivati…svaki prijedlog je dobrodošao. :wink:

Nije o tome u ovoj temi riječ :wink: Pisale se ili ne kompleksne/nekompleksne funkcije…ovako ionako je potrebna sintaksa za provjeru strukture objekta. Do toga si došao i sam spominjući sve druge koji rade istu stvar.

Što više oni ubace različitih pojmova da riješe jedan problem…moje mišljenje o njima postaje gore.
De pogledaj ih…imaju 10 različitih sintaksi da dohvate neku vrijednost pod ključu nekog objekta. I ta im sintaksa se razlikuje jel objekt “običan”, jel dynamic, jel dictionary, jel ovakav …jel onakav.
Brate mili, ako imaš objekt sa parovima ključ-value, onda mora biti jedna sintaksa da iz svih takvih objekta dohvaćaš value pod nekim ključem.
Oni su me naterali da normJS možda čak i takve najelementarnije stvari normalizira…jer su me začudili opako kako mogu jednostavno zakomplicirati.

Tebe da nema trebalo bi te izmisliti.

3 Likes

To se očito nekada desilo, za svakoga od nas :smiley: :smiley:

Mogao bih dosta toga napisati na receno ali necu, suzdrzat cu se :smiley:

Pa i JS ti trenutno ima obicni objekat i Map koji su dosta slicni (key/val store), a opet razliciti i imaju razlicite nacine za dohvatiti key :smiley:
Zasto je to tako ? Pa procitaj malo o nekim osnovnim strukturama podataka i vidjeti ces :smiley:

Ne, ne razumijem iskreno zašto bi to bilo tako…kad ja mogu napraviti metodu koja će normalizirati sintaksu za dohvat para key/value …da uvijek bude identičan.

Razumijem da objekt može imati prototype metode koje se isto nalaze pod ključem…te da na toj razini možemo klasificirati različite tipove ključeva.

I nekako je logično onda da foreach metoda neće u svakom svom mode-u iterirati kroz sve ključeve.

Što ne vidim preprekom da imamo i jedinstveni dohvat ključ/value za najnižu razinu, a tek onda se mogu ispravno graditi veće razine nad time.

E, ovo je lijep pridonos temi.

Ovo je na tragu ovoga što pravim … mada ovako na prvi letimičan prolaz ne vidim baš puno sintakse kako su to zamislili. A ovaj komad sintakse što su stavili pod example, i nije baš najsimpatičniji…

…kako god, fin dokument. Ako ništa drugo, bit će inspiracija za type-ove, kojih vidim su dosta uključili :slight_smile:

Ne.

Šta bi sa ol’ school

Number.isInteger(value)

?

password1 		- string koji je password minimalno težine 1

Evo nešto ozbiljnije (a ne samo zanimljivije):

1 Like

Čisto za usporedbu, ova njihova sintaksa:

{
    "type": "string",
    "contentMediaType": "application/jwt",
    "contentSchema": {
        "type": "array",
        "minItems": 2,
        "items": [
            {
                "const": {
                    "typ": "JWT",
                    "alg": "HS256"
                }
            },
            {
                "type": "object",
                "required": ["iss", "exp"],
                "properties": {
                    "iss": {"type": "string"},
                    "exp": {"type": "integer"}
                }
            }
        ]
    }
}

Bi se po mojoj sintaksi zapisalo: (Većinu toga sam prenio, nešto ih ovako na prvu nisam razumio…shvatit će se poanta i bez toga što nisam prenio.)

application_jwt[array{>1}[JWT, object[iss:string, exp:int]]]

Oni se koriste JSON strukturom da opišu strukturu objekta, što unosi podosta suvišnog codea.
Recimo, primjera radi…boldano je suvišno:

"required": [“iss”, “exp”],
"properties": {
“iss”: { “type” string"},
“exp”: {“type” : “integer”}
}

…ako se formulira sintaksa po kojoj će se znati gdje senalaze properties-i, i gdje se nalazi type nekog property-a.
Nadalje od toga, i navodnici oko string i integer su suvišni, ako imaš sintaksu unutar koje znaš tko je gdje.
Isto tako, ako se zna kako se popisuju required ključevi, onda je i ta notacija totalno suvišna i stvara redudanciju unutar sintakse.

Oni su opis te strukture ubacili u JSON formatu, pa im je nametnuto da poštuju JSON format.
A JSON i nije format koji je namjenjen i praktičan za ručno manerviranje…nego za računalnu serijalizaciju objekata. :slight_smile:

Zašto ne

password____1;// [double dunder] so we can always consider less amount of underscores for some other case in the future

Zaista nebitno koji singleTyp-ovi su unutra trenutno opisani. Ubacio sam neke random samo da prikažem mogućnosti.

Za razumjeti to trebaš imati barem neki nivo apstrakcije u sebi i razlikovati bitno od nebitnoga.

Da olakšam shvaćanje toga, stavio sam i napomenu:

//…typeovi su extendabilni, ali nativno bi funkcija trebala podržavati velik spektar specijalnih typeova

…koja tebi očito nije uspjela pomoći xd

Kad dodje do tebe i koda ništa drugo na forumu se nikad nije ni pročitalo.
Sad mi nedostaju evolucije, parne mašine, svemir. I Perina komponenta.

P.S. Lažem. Jesi na jednu temu striktno se drž’o tačno ispravne tematike al’ kratko je to trajalo.
Pustiću te da se pitaš šta je to tačno (od svega što si se dosad nalupet’o).

Hebate ledina, ako si uspio zaključiti da od specifičnih tipova:

MORE spec types:
    email           - string koji je email
    url             - string koji je url
    username        - string koji je username

    password        - string koji je password
    password1       - string koji je password minimalno težine 1
    password2       - string koji je password minimalno težine 2
    password5       - string koji je password minimalno težine 5

3/7 (43%) opada na nešto relativno specifično
a čak 4/7 (57%) opada na kontrolu isključivo passworda …i da je to krucijalno bitno u nečemu što predstavlja uopštenu sintaksu provjere strukture objekata.

Onda si gledao u krivi football. xd xd …i ne znam kako ti mogu pomoći da uočiš ono što je u ovoj priči bitno.

Da li sam to trebao navesti u gornjem pokaznom primjeru sintakse…vrlo vjerovatno nisam, što ne znači da je to leća kroz koju trebaš viditi sve.

Misliš, kada sam se jednom posvetio tebi da ti dokažem da si u zabludi i da muha neće srušiti zgradu ako se zabije u nju…da ti nisam dokazao da si imao tako bezvezne i krive pretpostavke?
Ali kada bi ja svaki puta tebi morao crtati objašnjenja…nebi me bilo xd xd…