Napsat pěkný, dobře navržený a dobře vypadající kód není tak těžké, jak se zdá. Vyžaduje to trochu úsilí, abyste se seznámili s hlavními pravidly a prostě je v kódu použili. A nemusí to být jako všechno najednou, ale jak se budete cítit pohodlně s jednou věcí, zkuste přemýšlet o další atd.
Vytvářejte solidní, nikoli hloupý kód
Začněme představením nejzákladnějších pravidel, která se nazývají SOLID. Jedná se o termín popisující soubor zásad pro dobrý návrh. kód kterou vymyslel Robert C. Martin, a jak to probíhá:
S znamená zásada jednotné odpovědnosti
Uvádí, že třída by měla mít jeden jediný důvod ke změně. Jinými slovy, třída by měla mít pouze jeden úkol, takže bychom se měli vyhnout psaní velkých tříd s mnoha povinnostmi. Pokud má naše třída dělat mnoho věcí, pak by každá z nich měla být delegována do samostatných.
třída Oznámení
def initialize(params)
@params = params
end
def call
EmailSender.new(message).call
end
private
def zpráva
# některé implementace
end
end
O znamená otevřený/uzavřený princip
Uvádí, že byste měli mít možnost rozšířit chování třídy, aniž byste ji měnili. Jinými slovy, třídu by mělo být možné snadno rozšířit, aniž by bylo nutné ji jakkoli upravovat. Toho můžeme dosáhnout např. pomocí vzoru strategie nebo dekorátorů.
třída Oznámení
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call zpráva
end
private
def zpráva
# některé implementace
end
end
třída EmailSender
def call(zpráva)
# některé implementace
end
end
třída SmsSender
def call(zpráva)
# některé implementace
end
end
Díky této konstrukci je možné přidávat nové odesílatele beze změny kódu.
L znamená Liskovův substituční princip
Uvádí, že odvozené třídy musí být nahraditelné svými základními třídami. Jinými slovy, použití tříd, které pocházejí od stejného předka, by mělo být snadno nahraditelné jiným potomkem.
třída Logger {
info (zpráva) {
console.info(this._prefixFor('info') + zpráva)
}
error (zpráva, err) {
console.error(this._prefixFor('error') + zpráva)
if (err) {
console.error(err)
}
}
_prefixFor (type) {
// nějaká implementace
}
}
class ScepticLogger extends Logger {
info (zpráva) {
super.info(zpráva)
console.info(this._prefixFor('info') + 'A to je vše, co jsem chtěl říct.')
}
error (zpráva, err) {
super.error(message, err)
console.error(this._prefixFor('error') + 'Velká věc!')
}
}
Název třídy můžeme snadno nahradit, protože obě třídy mají naprosto stejné rozhraní použití.
Mám na mysli princip segregace rozhraní.
Uvádí, že byste měli vytvořit jemně zrnitá rozhraní, která jsou specifická pro klienta. Co je to rozhraní? Je to poskytnutý způsob použití určité části kódu. Porušením tohoto pravidla tedy může být např. třída s příliš mnoha metodami, stejně jako metoda s příliš mnoha možnostmi argumentů. Dobrým příkladem pro vizualizaci tohoto principu je vzor úložiště, a to nejen proto, že do jedné třídy často vkládáme mnoho metod, ale také proto, že tyto metody jsou vystaveny riziku přijetí příliš mnoha argumentů.
# tentokrát není nejlepším příkladem
třída NotificationRepository
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
end
end
# a lepší
třída NotificationRepository
def find_all_by_ids(ids:)
Notification.where(id: ids)
end
def find_all_by_ids_info(ids:)
find_all_by_ids(ids).where(type: :info)
end
end
D znamená princip inverze závislosti
Uvádí, že byste se měli spoléhat na abstrakce, nikoliv na konkretizace. Jinými slovy, třída, která používá jinou třídu, by neměla být závislá na detailech její implementace, důležité je pouze uživatelské rozhraní.
třída Oznámení
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call zpráva
end
private
def zpráva
# některé implementace
end
end
O objektu sender potřebujeme vědět pouze to, že vystavuje metodu `call`, která očekává zprávu jako argument.
Není to nejlepší kód vůbec
Je také velmi důležité znát věci, kterým je třeba se při psaní kódu striktně vyhnout, takže zde je další sbírka STUPIDNÍCH zásad, které způsobují, že kód není udržovatelný, těžko se testuje a znovu používá.
S znamená Singleton
Singletony jsou často považovány za anti-vzorce a obecně je třeba se jim vyhnout. Hlavním problémem tohoto vzoru je však to, že je jakousi výmluvou pro globální proměnné/metody a vývojáři ho mohou rychle nadužívat.
T znamená těsné spojení
Je zachována, pokud změna v jednom modulu vyžaduje i změny v jiných částech aplikace.
U znamená netestovatelnost
Pokud je váš kód dobrý, pak by psaní testů mělo být zábavou, nikoli noční můrou.
P znamená předčasná optimalizace
Klíčové je zde slovo předčasně, pokud to nepotřebujete hned, je to ztráta času. Je lepší zaměřit se na dobrý, čistý kód než na nějaké mikrooptimalizace - což obecně způsobuje složitější kód.
Mám na mysli nepopisné pojmenování
Je to nejtěžší věc při psaní dobrého kódu, ale nezapomeňte, že to není jen pro zbytek vašeho kódu. tým ale i pro budoucnost, tak se k vám chovejte správně 🙂 Je lepší napsat dlouhý název metody, který ale řekne vše, než krátký a záhadný.
D znamená Duplikace
Hlavním důvodem duplikace v kódu je dodržování zásady těsného propojení. Pokud je váš kód těsně spřažený, nemůžete ho prostě znovu použít a vzniká duplicitní kód, proto dodržujte princip DRY a neopakujte se.
Teď to není důležité
Rád bych se také zmínil o dvou velmi důležitých věcech, které se často opomíjejí. O první z nich byste měli slyšet - je to YAGNI, což znamená: nebudete ji potřebovat. Čas od času tento problém pozoruji při revizi kódu nebo dokonce při psaní vlastního kódu, ale měli bychom přepnout své uvažování o implementaci funkce. Měli bychom napsat přesně takový kód, který právě v tuto chvíli potřebujeme, ne více nebo méně. Měli bychom mít na paměti, že vše se velmi rychle mění (zejména požadavky aplikací), takže nemá smysl myslet na to, že se něco jednou bude hodit. Neztrácejte čas.
Nerozumím tomu.
A poslední věc, která asi není úplně zřejmá a pro někoho může být dost kontroverzní, je popisný kód. Nemyslím tím jen používání správných názvů tříd, proměnných nebo metod. Je opravdu, ale opravdu dobré, když je celý kód čitelný na první pohled. K čemu slouží velmi krátký kód, zatímco je maximálně záhadný a nikdo kromě toho, kdo ho napsal, neví, co dělá? Podle mého názoru je lepší napsat několik znaků.příkazy k podmínkámněco jiného více než jedno slovo a pak včera sedí a přemýšlí: počkat, jaký je výsledek, jak se to stalo, a tak dále.
const params = [
{
movies: [
{ title: 'The Shawshank Redemption' },
{ title: 'One Flew Over the Cuckoo's Nest' }
]
},
{
filmy: [
{ název: "Saving Private Ryan" },
{ název: "Pulp Fiction" },
{ název: "The Shawshank Redemption" },
]
}
]
// první návrh
function uniqueMovieTitlesFrom (params) {
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(movie => movie.title)
return [...new Set(titles)]
}
// druhý návrh
function uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Shrnuto a podtrženo
Jak vidíte, je třeba si zapamatovat spoustu pravidel, ale jak jsem se zmínil na začátku, napsat pěkný kód je otázkou času. Pokud začnete přemýšlet o jednom zlepšení svých kódovacích návyků, uvidíte, že další dobré pravidlo bude následovat, protože všechny dobré věci vznikají samy od sebe stejně jako ty špatné.
Přečtěte si více:
Co je Ruby on Jets a jak pomocí něj vytvořit aplikaci?
Vuelendar. Nový projekt Codestu založený na Vue.js
Týdenní přehled nejlepších technických článků společnosti Codest. Tvorba softwaru pro 50 milionů souběžných soketů (10)