Sisäinen vs. ulkoistaminen: Ohjelmistokehityksen vertailu
Tutustu sisäisen ja ulkoistetun ohjelmistokehityksen lopulliseen vertailuun, jossa korostuvat kustannustehokkuus, kykyjen saatavuus ja Codestin poikkeukselliset kumppanuusedut.
Mukavan, hyvin suunnitellun ja hyvännäköisen koodin kirjoittaminen ei ole niin vaikeaa kuin miltä se näyttää. Se vaatii hieman vaivannäköä, jotta oppii tuntemaan tärkeimmät säännöt ja käyttää niitä koodissaan. Eikä kaikkea tarvitse tehdä kerralla, vaan kun tunnet olosi mukavaksi yhden asian kanssa, yritä miettiä toista, ja niin edelleen.
Aloitetaan esittelemällä alkeellisimmat säännöt, joita kutsutaan SOLID-säännöiksi. Se on termi, joka kuvaa Robert C. Martinin keksimää hyvän koodin suunnitteluperiaatteiden kokoelmaa, ja miten se toimii:
Siinä todetaan, että luokalla pitäisi olla yksi ja vain yksi syy muuttua. Toisin sanoen luokalla pitäisi olla vain yksi tehtävä, joten meidän pitäisi välttää kirjoittamasta suuria luokkia, joilla on monia vastuualueita. Jos luokkamme on tehtävä paljon asioita, jokainen niistä tulisi delegoida erillisiksi.
luokka Ilmoitus
def initialize(params)
@params = params
end
def call
EmailSender.new(message).call
end
private
def message
# jokin toteutus
end
end
Sen mukaan luokan käyttäytymistä pitäisi voida laajentaa muuttamatta sitä. Toisin sanoen luokan laajentamisen pitäisi olla helppoa ilman, että siihen tehdään muutoksia. Tämä voidaan saavuttaa esimerkiksi käyttämällä strategiamallia tai koristeita.
luokka Ilmoitus
def initialize(params, sender)
@params = params
@sender = lähettäjä
end
def call
sender.call message
end
private
def viesti
# jokin toteutus
end
end
luokka EmailSender
def call(message)
# jokin toteutus
end
end
luokka SmsSender
def call(message)
# jokin toteutus
end
end
Tämän mallin avulla on mahdollista lisätä uusia lähettäjiä muuttamatta mitään koodia.
Sen mukaan johdettujen luokkien on oltava korvattavissa perusluokillaan. Toisin sanoen samasta esi-isästä peräisin olevien luokkien käytön pitäisi olla helposti korvattavissa toisella jälkeläisellä.
luokka 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) {
// jokin toteutus
}
}
class ScepticLogger extends Logger {
info (message) {
super.info(message)
console.info(this._prefixFor('info') + 'Ja siinä kaikki mitä minulla oli sanottavaa.')
}
error (message, err) {
super.error(message, err)
console.error(this._prefixFor('error') + 'Iso juttu!')
}
}
Voimme helposti korvata luokan nimen, koska molemmilla on täsmälleen sama käyttöliittymä.
Siinä todetaan, että sinun pitäisi tehdä hienojakoisia, asiakaskohtaisia rajapintoja. Mikä on rajapinta? Se on tietyn koodin osan käyttötapa. Tämän säännön rikkominen voisi siis olla esimerkiksi luokka, jossa on liian monta metodia, tai metodi, jossa on liian monta argumenttivaihtoehtoa. Hyvä esimerkki tämän periaatteen havainnollistamiseksi on repository-kuvio, ei ainoastaan siksi, että usein laitamme yhteen luokkaan paljon metodeja, vaan myös siksi, että nämä metodit ovat alttiina riskille hyväksyä liian monta argumenttia.
# ei ole paras esimerkki tällä kertaa.
class IlmoitusVarasto
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
end
end
# ja parempi
class IlmoitusVarasto
def find_all_by_ids(ids:)
Notification.where(id: ids)
end
def find_all_all_by_ids_info(ids:)
find_all_all_by_ids(ids).where(type: :info)
end
end
Siinä todetaan, että sinun pitäisi tukeutua abstraktioihin, ei konkretioihin. Toisin sanoen luokan, joka käyttää toista luokkaa, ei pitäisi olla riippuvainen sen toteutuksen yksityiskohdista, vaan kaikki, mikä on tärkeää, on käyttöliittymä.
luokka Ilmoitus
def initialize(params, sender)
@params = params
@sender = lähettäjä
end
def call
sender.call message
end
private
def viesti
# jokin toteutus
end
end
Meidän tarvitsee tietää lähettäjäobjektista vain, että se tarjoaa `call`-metodin, joka odottaa viestin argumenttina.
On myös erittäin tärkeää tietää, mitä asioita pitäisi ehdottomasti välttää koodia kirjoitettaessa, joten tässä on toinen kokoelma typeriä periaatteita, jotka tekevät koodista vaikeasti ylläpidettävää, vaikeasti testattavaa ja uudelleenkäyttöä.
Singletoneja pidetään usein antikuvioina, ja niitä tulisi yleensä välttää. Tämän mallin suurin ongelma on kuitenkin se, että se on eräänlainen tekosyy globaaleille muuttujille/metodeille, ja kehittäjät voivat käyttää sitä nopeasti liikaa.
Se säilyy, kun muutos yhdessä moduulissa edellyttää muutoksia myös muissa sovelluksen osissa.
Jos koodisi on hyvä, testien kirjoittamisen pitäisi kuulostaa hauskalta, ei painajaiselta.
Sana "ennenaikainen" on tässä avainasemassa, sillä jos et tarvitse sitä nyt, se on ajanhukkaa. On parempi keskittyä hyvään, puhtaaseen koodiin kuin joihinkin mikro-optimointeihin, jotka yleensä aiheuttavat monimutkaisempaa koodia.
Se on vaikeinta hyvän koodin kirjoittamisessa, mutta muista, että se ei ole vain muulle tiimillesi vaan myös tulevalle itsellesi, joten kohtele itseäsi oikein 🙂 On parempi kirjoittaa metodille pitkä nimi, mutta se kertoo kaiken, kuin lyhyt ja arvoituksellinen nimi.
Tärkein syy koodin päällekkäisyyteen on tiukan kytkennän periaatteen noudattaminen. Jos koodisi on tiukasti kytketty, et voi käyttää sitä uudelleen ja päällekkäistä koodia syntyy, joten noudata DRY-periaatetta äläkä toista itseäsi.
Haluaisin myös mainita kaksi hyvin tärkeää asiaa, jotka usein jätetään mainitsematta. Teidän olisi pitänyt kuulla ensimmäisestä - se on YAGNI, joka tarkoittaa: ette tule tarvitsemaan sitä. Ajoittain havaitsen tämän ongelman tehdessäni koodin tarkistusta tai jopa kirjoittaessani omaa koodiani, mutta meidän pitäisi vaihtaa ajatteluamme ominaisuuden toteuttamisesta. Meidän pitäisi kirjoittaa juuri sitä koodia, jota tarvitsemme juuri tällä hetkellä, ei enempää tai vähempää. Meidän pitäisi pitää mielessä, että kaikki muuttuu hyvin nopeasti (erityisesti sovellusten vaatimukset), joten on turha ajatella, että jokin asia tulee vielä joskus tarpeeseen. Älä tuhlaa aikaasi.
Ja viimeinen asia, joka ei liene aivan itsestäänselvyys ja joka saattaa olla joillekin varsin kiistanalainen, on kuvaileva koodi. En tarkoita sillä vain oikeiden nimien käyttämistä luokille, muuttujille tai metodeille. On todella, todella hyvä, kun koko koodi on luettavissa ensi silmäyksellä. Mikä on hyvin lyhyen koodin tarkoitus, kun taas se on niin arvoituksellinen kuin se vain voi olla, eikä kukaan tiedä, mitä se tekee, paitsi sen kirjoittanut henkilö? Minun mielestäni on parempi kirjoittaa joitakin merkkejä.ehtolausekkeetjotain muuta kuin yksi sana ja sitten eilen istuu ja ihmettelee: odota, mikä on tulos, miten se tapahtui, ja niin edelleen.
const params = [
{
movies: [
{ title: 'The Shawshank Redemption' },
{ title: 'Yksi lensi yli käenpesän' } }
]
},
{
movies: [
{ title: 'Saving Private Ryan' },
{ title: 'Pulp Fiction' },
{ title: 'The Shawshank Redemption' },
]
}
]
// ensimmäinen ehdotus
function uniqueMovieTitlesFrom (params) {
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(elokuva => elokuva.title)
return [...new Set(titles)]
}
// toinen ehdotus
function uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Kuten huomaat, muistettavia sääntöjä on paljon, mutta kuten alussa mainitsin, hienon koodin kirjoittaminen on ajan kysymys. Jos alat miettiä yhtä parannusta koodaustottumuksiisi, huomaat, että toinen hyvä sääntö seuraa, koska kaikki hyvät asiat syntyvät itsestään aivan kuten huonotkin.
Lue lisää:
Mikä on Ruby on Jets ja miten rakentaa sovellus sen avulla?
1TP53Kalenteri. Uusi Codestin projekti, joka perustuu Vue.js:ään.