# ASSIGNMENT 1 - TOKENIZER ### Namngivning #### Generellt om Namgivning i mitt program: - **Avoid Disinformation** - Ingen av metod eller klassnamn innehåller förkortningar eller liknanade namn för olika saker. - **Make Meaningful Distinctions** - Jag har försökt undvika noice words, det man skulle kunna fundera över klassnamen för de olika grammatikerna som samtliga heter **PrefixGrammar** t.ex. WordGrammar och ArithmeticGrammar men det är olika grammatiker. - **Use searchable names** - Jag använder inga enstaviga ord eller variabler. Jag undviker iteratorer som kräver att det deklareas en variabel bara för att hålla koll på iterationen. - **Avoid Mental Mapping** - Jag använder långa och förklarande namn och försöker undervika förkortningar. Man skulle kunna se regex som en förkortningen men detta förekommer inte i någon publik metod. - **Don’t Be Cute** - Inga metoder använder sentimentala namn eller namn som ska anses vara "skojiga". | Namn och förklaring | Reflektion | | ------------------ | ---------- | | **Tokenizer** <br/> Namn på Klass | Detta klassnamn bockar av flera av de rubriker som tas upp i boken. <br/>Det finns ingen förkortning eller någonting annat i programmet som har ett liknande namn **(Avoid Disinformation)**. Det är också lätt att **uttala namnet / (Use Pronounceable Names)** <br/><br/> Klassens namn är ett **substantiv** vilket rekommenderas för klasser och beskriver klassens syfte bra **(Use Intention-Revealing Names)**, . Eventuellt skulle man kunna döpa den till StringTokenizer för att förtydliga att det är strängar som tokeniseras. | **WordGrammar** <br/> Namn på Klass | Detta klassnamn kan i viss mån ses som att det ger användaren disinformation **(Avoid disinformation)** då den faktiskt kan hantera både ord och punkter. | | **Tokenizer.getActiveToken** <br/> Metod på Tokenizer klassen. | Metoden är en **"verb-fras"** som använder sig av "standard" **prefixet** **get**.. för att visa att metoden hämtar något | | **Tokenizer.setActiveTokenToNext** <br/> **Tokenizer.setActiveTokenToPrevious** <br/> Metoder på Tokenizer klassen. | Även dessa använder sig aven **"verb-fras"** med **prefix** fast i detta fallet används **set** för att visa att det är ett värde som sätts om metoden körs. | | **Tokenizer.countTokens** <br/> Metod på Tokenizer klassen. | Även om detta namnet är en **"verb-fras"** kanske namnet bör ses över, vilka tokens är det som räknas. Inkluderar det eventuell token med lexicalt fel? räknas End token? **(Use Intention-Revealing Names)** | | **IndexError** <br/> Extends error. | Skulle kunna heta något med Exception för att förtydliga för den programmerare som använder vår tokenizer att detta är något som vi förväntar oss att denna ska hantera. | ### Funktioner #### Generellt om Funktioner i mitt program: - Genom att följa de punkter som tas upp i kapitel två om namgiving uppfyller metoder **Use Descriptive Names** som diskuteras i kapitel 3 om funktioner. - Metoder som börjar med # är privata metoder. - Det finns två metoder som är **Monadic** dessa är inte specificerade i tabellen nedan. Det är metoder som jag har lagt in på Tokenizer klassen för att kunna återanvända samma Tokenizer objekt flera gånger utan att skapa en ny Tokenizer. setNewLexicalGrammar(lexicalGrammar), setNewStringToTokenize(stringToTokenize). Parametrarna på dessa två metoder ska varken kontrolleras som boolska värden eller förändras i sig **(Common Monadic Forms)** och de ska heller inte ses som ett **Output Argument** då det är en input till vad som förändras på Tokenizer objektet och metoderna returnerar inte något till användaren. - - **Small** - Metoden är liten och mindre än de 20 rader som boken menar att man ska försöka hålla sig under <br/> | Namn och förklaring | Antal rader | Reflektion | | ------------------- | ----------- | ---------- | | **#addBestTokenMatch()**: Privat metod i Tokenizer klassen som kontrollerar en token mot bästa matching av token typ | 10 | **Blocks and indenting** I detta avsnitt diskuteras storleken på kod inom exempelvis en if/else-sats och att den bör endast vara en rad annars ska man fundera över om blocket borde kalla på en funktion. I detta fallet har jag valt att inte göra det eftersom att if blocket innehåller tre rader kod och else blocket fyra rader. Anledningen är att jag vill undvika en "explosion" av metoder och else blocket kan man egentligen se som en rad som pushar in ett objekt i en array och eftersom att objektet innehåller tre key/value par så vill jag lägga dessa på varsin egen rad för att gör koden mer lättläst. <br/> **Do one thing** Metoden kollar efter bästa tokenmatchning och lägger till detta i arrayen av tokens. Det man skulle kunna argumentera för är att jag även lägger till lexical-fel om ingen token hittas men jag anser att bästa matchningen då är att ingen token hittats och har därför valt att ha de i samma metod som ett if/else - statement | | **#matchStringWithRegex()**: Privat metod i Tokenizer som matchar en sträng mot angiven lexicalgrammatik och lägger till tokens i en array | 5 | **Don’t Repeat Yourself** - Metoden ittererar genom alla de olika typer av lexicala grammatiker som finns för grammtik som användaren angett och försöker matcha med den nuvurande strängen. <br/> **Blocks and Indenting** Även här finns en if-sats med ett block om fyra rader där man egentligen kan se det som en rad men då objektet innehåller tre key/value par så blir det tydligare att lägga de på varsin rad. <br/> **Do One Thing** - Kontrollerar en sträng mot samtliga lexicala grammatiker och lägger till matchande tokens i en array. | | **#createTokens()**: Privat metod i Tokenizer klassen som loopar igenom strängen som användaren angett och skapar tokens | 5 | **Reading Code from Top to Bottom: The Stepdown Rule** Denna klassen skapar alla tokens genom att ta strängen som angetts och bryta ner till tokens genom att kalla de två metoderna som nämnts tidigare i tabellen i en sekvens. <br/> **Have No Side Effects** Även att denna metod kallar på två andra metoder så anser jag att det inte skapas några sideffekter. Metoden ska skapa tokens och för att göra detta behöver vi matcha strängen mot en grammatik och sedan kontrollera efter bästa token matchning för att kunna skapa en token. <br/> **Blocks and indenting** Man skulle kunna ändra koden så att det bara skapas en token vid varje tillfälle man ber om en aktiv token. Detta är en fördel om vi får in en väldig lång sträng i vår kod då vi slipper skapa en token förrens den är aktuell. Däremot när jag gjorde på detta sättet så blev det en harang av if/else uttryck som var beroende av att komma i en viss ordning och jag valde därför att istället plocka ut samtliga tokens på en och samma gång. | | **getActiveToken()** metod i Tokenizer klassen som returnerar en aktiv token | 5 | **Switch Statements** - Jag hade en plan på att använda en switch sats i denna metod för att avgöra om jag ska returenera ett END objekt eller en aktiv token men eftersom boken avråder från detta då de av sin natur blir långa så valde jag istället att köra med if/else. <br/> **Reading Code from Top to Bottom: The Stepdown Rule** - Metoden kallar först på en metod för att kontrollera att aktiv token är "valid" och returnerar sedan aktiv token eller ett END objekt. | | **setActiveTokenToNext()**: Sets the active token to the next index | 5 | **Error Handling Is One Thing** - Jag har skapat egna klasser för att hantera fel. I denna metod kastas ett undantag (IndexError) om man försöker stega sig förbi END token. <br/> **Command Query Separation** Denna metoden sätter endast index för aktiv Token till nuvarande index plus ett eller kastar ett fel om index blir större än längden på array med tokens. Jag skickade till en början tillbaka den nya aktiva token direkt när användaren exekverade denna metod men eftersom att detta avsnitt säger att metoden ska antingen göra något ett besvara något, inte båda så valde jag att ta bort returen av aktiv token och använder får istället kalla på getActiveToken() efter att denna metod körts för att få ut data på ny aktiv token. Däremot så kontrollerar jag i denna metoden om det index man stegar till innehåller ett lexikalt fel och jag kastar då direkt ett undantag vilket man också skulle kunna flytta och endast ha på getActiveToken(). Men jag gör på detta sättet eftersom att lexikala fel ligger sist i arrayen av tokens och användaren ska inte kunna stega sig vidare eller få detta som aktivt token |