Uzrakstīt skaistu, labi izstrādātu un labi izskatīgu kodu nav tik grūti, kā šķiet. Tas prasa nelielu piepūli, lai iepazītos ar galvenajiem noteikumiem un vienkārši izmantotu tos savā kodā. Un tas nav jādara kā viss uzreiz, bet, kad jūtaties ērti ar vienu lietu, mēģiniet padomāt par citu, un tā tālāk.
Veidojiet stabilu, nevis muļķīgu kodu
Sāksim ar elementārākajiem noteikumiem, kurus sauc par SOLID. Tas ir termins, kas apraksta dizaina principu kopumu, lai nodrošinātu labu dizainu. kods ko izgudroja Roberts K. Martins, un kā tas notiek:
S - vienotas atbildības princips
Tajā noteikts, ka klasei jābūt vienam un tikai vienam iemeslam, lai to mainītu. Citiem vārdiem sakot, klasei vajadzētu būt tikai vienam uzdevumam, tāpēc mums vajadzētu izvairīties no lielu klašu ar daudziem pienākumiem rakstīšanas. Ja mūsu klasei ir jāveic daudz lietu, tad katra no tām būtu jādeleģē atsevišķās klasēs.
klase Paziņojums
def initialize(params)
@params = params
end
def call
EmailSender.new(message).call
end
privāts
def ziņojums
# dažas implementācijas
beigas
beigas
O nozīmē atvērts/aizvērts princips
Tajā ir noteikts, ka ir jābūt iespējai paplašināt klases uzvedību, nemainot to. Citiem vārdiem sakot, ir jābūt iespējai viegli paplašināt klasi, neveicot tajā nekādas modifikācijas. To var panākt, piemēram, izmantojot stratēģijas modeli vai dekoratorus.
klase Paziņojums
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call message
end
privāts
def message
# dažas implementācijas
beigas
beigas
klase EmailSender
def call(message)
# dažas implementācijas
end
end
klase SmsSender
def call(message)
# dažas implementācijas
end
end
Izmantojot šo konstrukciju, ir iespējams pievienot jaunus sūtītājus, nemainot kodu.
L ir Liškova aizvietošanas princips
Tajā noteikts, ka atvasinātajām klasēm jābūt aizvietojamām ar savām bāzes klasēm. Citiem vārdiem sakot, to klašu lietojumam, kas nāk no viena priekšteča, jābūt viegli aizvietojamam ar citu pēcteci.
klase Logger {
info (ziņojums) {
console.info(this._prefixFor('info') + ziņojums)
}
error (message, err) {
console.error(this._prefixFor('error') + ziņojums)
if (err) {
console.error(err)
}
}
_prefixFor (type) {
// kāda implementācija
}
}
klase ScepticLogger extends Logger {
info (ziņojums) {
super.info(message)
console.info(this._prefixFor('info') + 'Un tas ir viss, ko man vajadzēja pateikt.')
}
error (message, err) {
super.error(message, err)
console.error(this._prefixFor('error') + 'Liela problēma!')
}
}
Mēs varam viegli nomainīt klases nosaukumu, jo abām klasēm ir tieši tāds pats lietošanas interfeiss.
Es domāju Interfeisa segregācijas princips
Tajā teikts, ka ir jāizveido smalkgraudainas saskarnes, kas ir specifiskas klientam. Kas ir saskarne? Tas ir paredzēts veids, kā izmantot kādu koda daļu. Tātad šī noteikuma pārkāpums varētu būt, piemēram, klase ar pārāk daudz metodēm, kā arī metode ar pārāk daudz argumentu iespējām. Labs piemērs šī principa vizualizēšanai ir repozitorija modelis, ne tikai tāpēc, ka mēs bieži vien vienā klasē ievietojam daudz metožu, bet arī tāpēc, ka šīs metodes ir pakļautas riskam pieņemt pārāk daudz argumentu.
# nav labākais piemērs šoreiz
klase NotificationRepository
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
end
end
# un labāks
klase 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 atkarības inversijas princips
Tajā teikts, ka jums ir jāpaļaujas uz abstrakcijām, nevis uz konkrētībām. Citiem vārdiem sakot, klasei, kas izmanto citu klasi, nevajadzētu būt atkarīgai no tās implementācijas detaļām, svarīga ir tikai lietotāja saskarne.
klase Paziņojums
def initialize(params, sender)
@params = params
@sender = sender
end
def call
sender.call message
end
privāts
def message
# dažas implementācijas
beigas
beigas
Viss, kas mums jāzina par sender objektu, ir tas, ka tas piedāvā `call` metodi, kas kā argumentu sagaida ziņojumu.
Nav labākais kods jebkad
Ir arī ļoti svarīgi zināt lietas, kas būtu stingri jāizvairās, rakstot kodu, tāpēc šeit iet vēl vienu kolekciju ar STUPID principiem, kas padara kodu nav uzturējams, grūti testēt, un atkārtoti izmantot.
S nozīmē Singleton
Atsevišķi vienskaitļi bieži tiek uzskatīti par pretveidiem, un parasti no tiem ir jāizvairās. Taču galvenā problēma ar šo modeli ir tā, ka tas ir sava veida attaisnojums globālajiem mainīgajiem/metodēm, un izstrādātāji to var ātri pārspīlēt.
T nozīmē cieša savienošana
Tas tiek saglabāts, ja izmaiņas vienā modulī prasa izmaiņas arī citās lietojumprogrammas daļās.
U ir nepārbaudāmība
Ja jūsu kods ir labs, tad testu rakstīšanai vajadzētu būt jautrai, nevis murgam.
P nozīmē priekšlaicīga optimizācija
Šeit galvenais ir vārds priekšlaicīgi - ja jums tas nav nepieciešams tagad, tad tā ir laika izšķiešana. Labāk koncentrēties uz labu, tīru kodu, nevis uz mikrooptimizācijām, kas parasti rada sarežģītāku kodu.
Es domāju Indescriptive Naming
Tā ir visgrūtākā lieta laba koda rakstīšanā, taču atcerieties, ka tā ir ne tikai pārējā jūsu kodā. komanda bet arī nākotnes jums, tāpēc izturieties pareizi 🙂 Labāk uzrakstīt garu metodes nosaukumu, bet tas pasaka visu, nekā īsu un mīklainu.
D ir dublēšana
Galvenais iemesls, kāpēc kods tiek dublēts, ir ciešas sasaistes principa ievērošana. Ja jūsu kods ir cieši saistīts, jūs vienkārši nevarat to atkārtoti izmantot un parādās dublēts kods, tāpēc ievērojiet DRY principu un neatkārtojiet sevi.
Šobrīd tas nav svarīgi
Vēlos pieminēt arī divas ļoti svarīgas lietas, kuras bieži vien netiek pieminētas. Par pirmo no tām jums jau vajadzēja dzirdēt - tā ir YAGNI, kas nozīmē: jums tas nebūs vajadzīgs. Laiku pa laikam es novēroju šo problēmu, veicot koda pārskatīšanu vai pat rakstot savu kodu, taču mums vajadzētu mainīt domāšanu par kādas funkcijas ieviešanu. Mums ir jāraksta tieši tāds kods, kāds mums ir nepieciešams tieši šajā brīdī, nevis vairāk vai mazāk. Mums jāpatur prātā, ka viss mainās ļoti ātri (īpaši lietojumprogrammu prasības), tāpēc nav jēgas domāt, ka kaut kas kādreiz noderēs. Netērējiet savu laiku.
Es nesaprotu
Un pēdējā lieta, kas, manuprāt, nav īsti acīmredzama un dažiem var šķist diezgan pretrunīga, ir aprakstošais kods. Ar to es nedomāju tikai pareizu nosaukumu lietošanu klasēm, mainīgajiem vai metodēm. Tas ir ļoti, ļoti labi, ja viss kods ir izlasāms no pirmā acu uzmetiena. Kāds ir ļoti īsa koda mērķis, turpretī tas ir tik mīklains, cik vien var būt, un neviens nezina, ko tas dara, izņemot cilvēku, kas to rakstījis? Manuprāt, labāk ir uzrakstīt dažas zīmes.nosacījumu paziņojumikaut ko vairāk nekā vienu vārdu, un tad vakar sēdēja un brīnījās: pagaidiet, kāds ir rezultāts, kā tas notika, un tā tālāk.
const params = [
{
filmas: [
{ title: 'The Shawshank Redemption' },
{ title: 'One Flew Over the Cuckoo's Nest' }
]
},
{
filmas: [
{ nosaukums: 'Saving Private Ryan' },
{ nosaukums: "Pulp Fiction" },
{ nosaukums: "The Shawshank Redemption" },
]
}
]
// pirmais piedāvājums
funkcija uniqueMovieTitlesFrom (params) {
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(movie => movie.title)
return [...new Set(titles)]
}
// otrais piedāvājums
funkcija uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Apkopojot
Kā redzat, ir daudz noteikumu, kas jāatceras, bet, kā jau minēju sākumā, jauka koda rakstīšana ir laika jautājums. Ja sāksiet domāt par vienu kodēšanas paradumu uzlabošanu, tad redzēsiet, ka sekos vēl viens labs noteikums, jo visas labās lietas rodas pašas no sevis, tāpat kā sliktās.
Lasīt vairāk:
Kas ir Ruby on Jets un kā ar to izveidot lietotni?
1TP61Kalendārijs. Jauns Codest projekts, kas balstīts uz Vue.js
Codest iknedēļas pārskats par labākajiem tehnoloģiju rakstiem. Programmatūras veidošana 50M vienlaicīgu ligzdu (10)