Að skrifa fallega, vel hannaða og aðlaðandi kóða er ekki eins erfitt og það virðist. Það krefst smá fyrirhafnar að kynnast helstu reglum og beita þeim í kóðanum þínum. Og það þarf ekki að vera allt í einu; þegar þú verður öruggur með eitt atriði skaltu hugsa um næsta, og svo framvegis.
Búðu til traustan kóða, ekki heimskulegan kóða.
Byrjum á því að kynna einföldustu reglurnar sem kallast SOLID. Það er hugtak sem lýsir safni hönnunarreglna fyrir gott kóði sem var fundið upp af Robert C. Martin og hvernig það gengur:
S þýðir meginreglan um eina ábyrgð.
Þar segir að flokkur eigi að hafa eina og aðeins eina ástæðu til að breytast. Með öðrum orðum á flokkur að hafa aðeins eitt verkefni, svo við ættum að forðast að skrifa stóra flokka með mörgum ábyrgðum. Ef flokkurinn okkar þarf að gera margt, ætti hvert þeirra að vera falið í sérstaka flokka.
class Notification
def initialize(params)
@params = params
end
def call
EmailSender.new(message).call
end
private
def message
# some implementation
end
end
O merkir opnunar- og lokunarreglan
Þar segir að þú ættir að geta stækkað hegðun bekkjar án þess að breyta honum. Með öðrum orðum ætti að vera auðvelt að stækka bekk án nokkurra breytinga á honum. Við getum náð þessu t.d. með því að nota stefnumynstur eða skreytingar.
class Notification
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call message
end
private
def message
# some implementation
end
end
class EmailSender
def call(message)
# einhver innleiðing
end
end
class SmsSender
def call(message)
# einhver innleiðing
end
end
Með þessari hönnun er hægt að bæta við nýjum sendurum án þess að breyta neinum kóða.
L þýðir Liskov-skiptireglan
Þar segir að afleiddar flokkar skuli vera skiptanlegar fyrir grunnflokka sína. Með öðrum orðum ætti að vera auðvelt að skipta út notkun flokka sem eiga sama forföður fyrir aðra niðinga.
class Logger {
info (message) {
console.info(this._prefixFor('info') + message)
}
error (message, err) {
console.error(this._prefixFor('error') + message)
if (err) {
console.error(err)
}
}
_prefixFor (type) {
// einhver útfærsla
}
}
class ScepticLogger extends Logger {
info (message) {
super.info(message)
console.info(this._prefixFor('info') + 'Og það er allt sem ég hafði að segja.')
}
error (message, err) {
super.error(message, err)
console.error(this._prefixFor('error') + 'Stórmál!')
}
}
Við getum auðveldlega skipt út nafni bekkjarins, því báðir hafa nákvæmlega sama notendaviðmót.
Ég á við aðskilnaðarskilyrði viðmóta
Þar er sagt að þú eigir að búa til fínkorna viðmót sem eru sérsniðin að viðskiptavininum. Hvað er viðmót? Það er veitt leið til notkunar á einhverjum hluta kóðans. Þannig gæti brot á þessari reglu verið t.d. flokkur með of mörgum aðferðum sem og aðferð með of mörgum rökvalkostum. Gott dæmi um að sýna þetta meginreglu er geymslumynstur (repository pattern), ekki aðeins vegna þess að við setjum oft marga aðferðir í einn flokk heldur einnig vegna þess að þessar aðferðir eru í hættu á að þurfa að taka við of mörgum rökum.
# ekki besta dæmið að þessu sinni
class NotificationRepository
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
end
end
# og betri útgáfa
class 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 þýðir meginreglan um gagnstæðu háðni.
Þar segir að þú eigir að treysta á abstraktjónir, ekki á konkretjónir. Með öðrum orðum, flokkur sem notar annan ætti ekki að treysta á innleiðingartengdar smáatriði, allt sem skiptir máli er notendaviðmótið.
class Notification
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call message
end
private
def message
# some implementation
end
end
Allt sem við þurfum að vita um sendandahlutinn er að hann býður upp á `call`-aðferð sem tekur skilaboðin sem rök.
Ekki besta kóðinn sem til hefur verið
Það er líka mjög mikilvægt að vita hvað beri að forðast alfarið þegar kóði er skrifaður, svo hér er enn ein safn STUPID-reglna sem gera kóðann óviðhaldanlegan, erfiðan í prófunum og endurnýtingu.
S þýðir Singleton
Singleton-mynstur eru oft talin andmynstur og almennt ætti að forðast þau. En helsta vandamálið við þetta mynstur er að það er eins konar afsökun fyrir alþjóðlegum breytum og aðferðum og þróunaraðilar geta fljótt misnotað það.
T þýðir þröng tenging
Það er varðveitt þegar breyting í einum einingum krefst einnig breytinga í öðrum hlutum forritsins.
U þýðir óprófanleiki
Ef kóðinn þinn er góður, ætti að skrifa prófanir að hljóma eins og skemmtilegt verkefni, ekki martröð.
P þýðir fyrirfram hagræðing
Orðið "premature" er lykilatriðið hér; ef þú þarft það ekki núna er það tímaeyðsla. Betra er að einbeita sér að góðum, hreinum kóða en smá-fínstillingum – sem almennt leiða til flóknari kóða.
Ég á við ólýsingarlegt nafngift.
Það er það erfiðasta við að skrifa góðan kóða, en mundu að það er ekki einungis fyrir restina af þínum lið en einnig fyrir framtíðarr þig, svo komdu vel fram við þig 🙂 Það er betra að skrifa langt nafn aðferðar sem segir allt en stutt og dularfullt nafn.
D þýðir endurtekning
Aðalástæðan fyrir endurtekningu kóða er að fylgja meginreglunni um þröngt tengslanet. Ef kóðinn þinn er þétt tengdur geturðu einfaldlega ekki endurnýtt hann og endurtekinn kóði birtist, svo fylgdu DRY og endurtaktu þig ekki.
Það skiptir ekki raunverulega máli núna.
Ég vil einnig nefna tvö mjög mikilvæg atriði sem oft eru skilin út. Þú ættir að hafa heyrt um hið fyrra – það er YAGNI sem þýðir: þú ætlar ekki að þurfa það. Frá tíma til tíma tek ég eftir þessu vandamáli þegar ég er að fara yfir kóða eða jafnvel skrifa minn eigin kóða, en við ættum að breyta hugsunarhætti okkar varðandi innleiðingu eiginleika. Við ættum að skrifa nákvæmlega þann kóða sem við þurfum á þessu augnabliki, hvorki meira né minna. Við verðum að hafa í huga að allt breytist mjög hratt (sérstaklega kröfur forritsins), svo það er tilgangslaust að hugsa að eitthvað muni einhvern tíma nýtast. Ekki sóa tíma þínum.
Ég skil ekki
Og síðasta atriðið, sem er kannski ekki alveg augljóst og gæti reynst nokkrum nokkuð umdeilt, er að þetta er lýsandi kóði. Ég á ekki við að nota eingöngu rétt nöfn fyrir klassa, breytur eða aðferðir. Það er virkilega, virkilega gott þegar kóðinn er læsilegur frá fyrstu sýn. Hver er tilgangurinn með mjög stuttan kóða sem er eins dularfullur og hægt er og enginn veit hvað hann gerir nema sá sem skrifaði hann? Að mínu mati er betra að skrifa nokkur stöfskilyrðissetningareinhver annað sem er meira en eitt orð og svo í gær sat ég og velti fyrir mér: bíddu, hver var niðurstaðan, hvernig það gerðist, og svo framvegis.
const params = [
{
movies: [
{ title: 'The Shawshank Redemption' },
{ title: 'One Flew Over the Cuckoo's Nest' }
]
},
{
movies: [
{ title: 'Saving Private Ryan' },
{ title: 'Pulp Fiction' },
{ title: 'The Shawshank Redemption' },
]
}
]
// fyrsta tillaga
function uniqueMovieTitlesFrom (params) {
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(movie => movie.title)
return [...new Set(titles)]
}
// önnur tillaga
function uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Til að draga saman
Eins og þú sérð eru mörg reglur sem þarf að muna, en eins og ég nefndi í byrjun er að skrifa fallega kóða spurning um tíma. Ef þú byrjar að hugsa um eina umbót á kóðunarvenjum þínum munt þú sjá að önnur góð regla mun fylgja, því allt sem gott er sprettur af sjálfu sér, rétt eins og hið slæma.
Lesa meira:
Hvað er Ruby on Jets og hvernig á að búa til forrit með því?
Vuelendar. Nýtt verkefni Codest byggt á Vue.js
Viktorlega skýrsla Codest um bestu tæknigreinar. Að byggja hugbúnað fyrir 50 milljónir samtímis sokka (10)