Een mooie, goed ontworpen en goed uitziende code schrijven is niet zo moeilijk als het lijkt. Het kost een beetje moeite om de belangrijkste regels te leren kennen en ze gewoon te gebruiken in je code. En je hoeft niet alles in één keer te doen, maar als je je comfortabel voelt met één ding, probeer dan aan een ander te denken, enzovoort.
Bouw solide, geen domme code
Laten we beginnen met het introduceren van de meest elementaire regels die SOLID worden genoemd. Het is een term die een verzameling ontwerpprincipes beschrijft voor goede code dat werd uitgevonden door Robert C. Martin en hoe het gaat:
S staat voor Enkelvoudig Verantwoordelijkheidsbeginsel
Het stelt dat een klasse slechts één reden moet hebben om te veranderen. Met andere woorden, een klasse zou maar één taak moeten hebben, dus we zouden het schrijven van grote klassen met veel verantwoordelijkheden moeten vermijden. Als onze klasse veel dingen moet doen, dan moet elk van die dingen worden gedelegeerd in aparte.
Klasse Melding
def initialiseer(params)
@params = params
einde
def oproep
EmailSender.new(bericht).call
einde
privé
def bericht
# enige implementatie
einde
einde
O betekent Open/Gesloten principe
Hierin staat dat je het gedrag van een class moet kunnen uitbreiden zonder deze aan te passen. Met andere woorden, het moet eenvoudig zijn om een klasse uit te breiden zonder deze aan te passen. We kunnen dit bijvoorbeeld bereiken door strategy pattern of decorators te gebruiken.
Klasse Melding
def initialiseer(params, afzender)
@params = params
@sender = afzender
einde
def oproep
afzender.oproep bericht
einde
privé
def bericht
# enige implementatie
einde
einde
klasse e-mailverzender
def oproep(bericht)
# enige implementatie
einde
einde
klasse sms-verzender
def oproep(bericht)
# enige implementatie
einde
einde
Met dit ontwerp is het mogelijk om nieuwe afzenders toe te voegen zonder code te wijzigen.
L betekent Liskov substitutieprincipe
Het stelt dat afgeleide klassen vervangbaar moeten zijn voor hun basisklassen. Met andere woorden, het gebruik van klassen die van dezelfde voorouder komen, moet eenvoudig te vervangen zijn door andere afstammelingen.
klasse Logger {
info (message) {
console.info(this._prefixFor('info') + bericht)
}
error (bericht, err) {
console.error(this._prefixFor('error') + bericht)
if (err) {
console.error(err)
}
}
_prefixFor (type) {
// sommige implementatie
}
}
class ScepticLogger extends Logger {
info (message) {
super.info(bericht)
console.info(this._prefixFor('info') + 'En dat is alles wat ik te zeggen had.')
}
error (bericht, err) {
super.error(bericht, err)
console.error(this._prefixFor('error') + 'Big deal!')
}
}
We kunnen de naam van de klasse eenvoudig vervangen, omdat beide exact dezelfde gebruiksinterface hebben.
Ik bedoel Interface Segregatie Principe
Het stelt dat je fijnkorrelige interfaces moet maken die klantspecifiek zijn. Wat is een interface? Het is een bepaalde manier van gebruik van een deel van de code. Een schending van deze regel kan dus bijvoorbeeld een klasse zijn met te veel methodes of een methode met te veel argumentopties. Een goed voorbeeld om dit principe te visualiseren is het repository patroon, niet alleen omdat we vaak veel methoden in een enkele klasse stoppen, maar ook omdat die methoden het risico lopen om te veel argumenten te accepteren.
# niet het beste voorbeeld deze keer
klasse KennisgevingRepository
def find_all_by_ids(ids:, info:)
meldingen = Melding.waar(id: ids)
info ? notifications.where(type: :info) : meldingen
einde
einde
# en een betere
Klasse MeldingenRepository
def find_all_by_ids(ids:)
Melding.waar(id: ids)
einde
def find_all_by_ids_info(ids:)
find_all_by_ids(ids).where(type: :info)
einde
einde
D betekent afhankelijkheidsomkeringsprincipe
Het stelt dat je afhankelijk moet zijn van abstracties, niet van concreties. Met andere woorden, een klasse die een andere klasse gebruikt zou niet afhankelijk moeten zijn van de implementatiedetails, het enige wat belangrijk is, is de gebruikersinterface.
Klasse Melding
def initialiseer(params, afzender)
@params = params
@sender = afzender
einde
def oproep
afzender.oproep bericht
einde
privé
def bericht
# enige implementatie
einde
einde
Alles wat we moeten weten over het object sender is dat het de `call` methode blootlegt die het bericht als argument verwacht.
Niet de beste code ooit
Het is ook heel belangrijk om te weten welke dingen strikt vermeden moeten worden tijdens het schrijven van code, dus hier volgt nog een verzameling met STUPID principes die code niet onderhoudbaar, moeilijk te testen en te hergebruiken maken.
S betekent Singleton
Singletons worden vaak beschouwd als antipatronen en moeten over het algemeen worden vermeden. Maar het grootste probleem met dit patroon is dat het een soort excuus is voor globale variabelen/methodes en snel overmatig gebruikt kan worden door ontwikkelaars.
T betekent Dichte koppeling
Het wordt bewaard wanneer een wijziging in één module ook wijzigingen in andere delen van de applicatie vereist.
U staat voor Ontoetsbaarheid
Als je code goed is, dan zou het schrijven van tests leuk moeten klinken in plaats van een nachtmerrie.
P betekent Premature Optimalisatie
Het woord voorbarig is hier de sleutel, als je het nu niet nodig hebt dan is het tijdverspilling. Het is beter om je te richten op een goede, schone code dan op wat micro-optimalisaties - die over het algemeen complexere code veroorzaken.
Ik bedoel indescriptieve naamgeving
Het is het moeilijkste bij het schrijven van goede code, maar vergeet niet dat het niet alleen voor de rest van je team maar ook voor jou in de toekomst, dus behandel je goed 🙂 Het is beter om een lange naam te schrijven voor een methode, maar het zegt alles, dan een korte en raadselachtige naam.
D betekent duplicatie
De belangrijkste reden voor duplicatie in code is het volgen van het principe van strakke koppeling. Als je code strak gekoppeld is, kun je het niet hergebruiken en verschijnt er dubbele code, dus volg DRY en herhaal jezelf niet.
Het is nu niet echt belangrijk
Ik wil ook twee heel belangrijke dingen noemen die vaak worden weggelaten. Over de eerste moet je gehoord hebben - het is YAGNI wat betekent: je hebt het niet nodig. Van tijd tot tijd zie ik dit probleem wanneer ik code review of zelfs mijn eigen code schrijf, maar we moeten onze denkwijze over het implementeren van een functie veranderen. We moeten precies die code schrijven die we op dit moment nodig hebben, niet meer of minder. We moeten in gedachten houden dat alles heel snel verandert (vooral applicatie-eisen), dus het heeft geen zin om te denken dat iets ooit van pas zal komen. Verspil je tijd niet.
Ik begrijp het niet
En het laatste, niet echt voor de hand liggend denk ik, en misschien nogal controversieel voor sommigen, is een beschrijvende code. Daarmee bedoel ik niet alleen het gebruik van de juiste namen voor klassen, variabelen of methoden. Het is echt heel goed als de hele code op het eerste gezicht leesbaar is. Wat is het doel van de zeer korte code terwijl het zo raadselachtig is als het maar kan en niemand weet wat het doet, behalve de persoon die het geschreven heeft? Naar mijn mening is het beter om een aantal karakters te schrijvenconditieverklaringeniets anders meer dan één woord en dan gisteren zitten en zich afvragen: wacht wat is het resultaat, hoe is het gebeurd, enzovoort.
const params = [
{
films: [
{titel: 'The Shawshank Redemption' },
{titel: 'One Flew Over the Cuckoo's Nest' } }
]
},
{
films: [
{titel: 'Saving Private Ryan' },
{titel: 'Pulp Fiction' },
{titel: 'The Shawshank Redemption' },
]
}
]
// eerste voorstel
functie uniqueMovieTitlesFrom (params) {
const titels = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(movie => movie.title)
return [...new Set(titles)]
}
// tweede voorstel
functie uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Samengevat
Zoals je ziet zijn er veel regels om te onthouden, maar zoals ik in het begin al zei is het schrijven van mooie code een kwestie van tijd. Als je begint na te denken over één verbetering van je codeergewoonten, dan zul je zien dat een andere goede regel zal volgen, omdat alle goede dingen uit zichzelf ontstaan, net als de slechte.
Lees meer:
Wat is Ruby on Jets en hoe bouw je er een app mee?
Vuekalender. Een nieuw project van Codest gebaseerd op Vue.js
Codest's wekelijkse verslag van de beste tech-artikelen. Software bouwen voor 50M gelijktijdige sockets (10)