Mikuláš je tu! Získaj 90 % extra kreditov ZADARMO s promo kódom CERTIK90 pri nákupe od 1 199 kreditov. Len do nedele 7. 12. 2025! Zisti viac:
NOVINKA: Najžiadanejšie rekvalifikačné kurzy teraz s 50% zľavou + kurz AI ZADARMO. Nečakaj, táto ponuka dlho nevydrží! Zisti viac:

2. diel - Najčastejšie chyby programátorov - Vieš pomenovať objekty?

V minulej lekcii, Najčastejšie chyby programátorov - Vieš pomenovať premenné?, sme si ukázali najčastejšie chyby začiatočníkov, ktorých sa dopúšťajú pri pomenovaní premenných.

V dnešnom tutoriále kurzu Best practices pre návrh softvéru si ukážeme prvé dobré praktiky pre objektovo orientované programovanie. Budeme sa zaoberať najmä správnym pomenovávaním tried, metód a atribútov. Pozrite sa, či nerobíte jednu z najčastejších chýb.

Miliónové straty

O dobrých praktikách sme sa už bavili a vieme, že neprehľadné programy nie sú žiadna malichernosť. Sú totiž:

  • Nezrozumiteľné pre ostatných - Keď tím 5 programátorov, každý s platom 5 000 € mesačne, strávi 20 % pracovnej doby lúštením kódu, stojí to ročne 60 000 €!
  • Náchylné k chybám - Tržby aj malých e-shopov sú mesačne obvykle v stovkách tisíc eur, 1 deň nefunkčnosti teda stojí majiteľa desiatky tisíc eur, dodávateľovi hrozia nemalé zmluvné pokuty.
  • Prakticky nerozšíriteľné - V súčasnej funkčnosti sa už nikto nevyzná a nemožno ju rozšíriť. Programátorský tím o niekoľkých ľuďoch musí vytvoriť aplikáciu znova, sme opäť v stovkách tisíc eur.
  • Netestovateľné, nezabezpečené a takto by sme mohli pokračovať.

Niet pochýb, že dobré praktiky sú pre vývoj softvéru v tíme úplne zásadné a následky ich porušenia sú potom fatálne.

Ako správne pomenovávať triedy, atribúty a metódy?

V dnešnej lekcii sa budeme zaoberať „objektovými súčiastkami“, z ktorých sú naše aplikácie zložené. Naučíme sa ich správne pomenovať, aby boli prehľadné.

Motivačný príklad

K doktorovi príde pacient a hovorí mu, že má problém so svojím orgánom Move. Nefunguje mu shoe. Pacient sa zdá byť nejaký popletený a doktorovi trvá pomerne dlho, kým z neho dostane, že ho pichá v päte a preto si nemôže obuť ani topánku. Keď konečne vypustí pacienta z ordinácie, zistí, že bol súčasťou skupiny a takých ich tam ešte čaká niekoľko desiatok.

Best practices pre návrh softwaru

Pozrime sa ešte na druhý príbeh. Programátorovi pridelí program, ktorý spadne s chybou v triede MoveData, metóda data(). Program sa zdá byť nejaký popletený a programátorovi trvá dlho, než zistí, že ide o triedu importujúcu dáta z externej zálohy a že sa prvýkrát musí ručne zavolať metóda work(), ktorá import vykoná. Keď chybu konečne opraví, objaví sa ďalšia a zistí, že v programe je niekoľko desiatok tried a metód, z ktorých názvu vôbec nespozná, čo robia.

Určite vidíme paralelu týchto dvoch príbehov. Zatiaľ čo u ľudského tela by nám asi ťažko napadlo hovoriť o orgáne "presúvať" a funkcii "topánka", v programoch bohužiaľ nie je taký problém naraziť na objekty pomenované ako deje a funkcie pomenované ako veci, aj keď je princíp úplne rovnaký. Niet divu, že si Indescriptive naming vyslúžilo svoje miesto v šestici najhorších programátorských praktík STUPID.

Pomenovanie tried

Triedy definujú objekty, z ktorých je aplikácia zložená. Z toho vyplýva niekoľko triviálnych pravidiel. Názvy tried:

  • sú podstatné mená! - Ide o jednotlivé počítateľné objekty bez ohľadu na to, koľko objektov od triedy potom vytvoríme.
  • nie sú názvy dejov - Ide o objekty (veci). Triedy teda nemôžeme nazvať napr. WorkWithFile alebo Printing, ale napr. FileManager alebo Printer (alebo ešte lepšie UserInterface, pretože málokedy tvoríme celú triedu len na vypísanie niečoho).
  • začínajú veľkým písmenom - Každé ďalšie slovo má veľké písmeno (notácia PascalCase a to aj v Pythone). Je tak vidieť, že ide o všeobecnú triedu a nie o jej konkrétnu inštanciu.
  • pomenované podľa toho, akú súčasť programu reprezentujú, čo nemusí byť vždy rovnaké, ako to, čo vo vnútri robia.

Ukážme si niekoľko príkladov:

  • ✗ Nesprávne

    class employee {
    class Employees {
    class Invoiceitem {
    class WorkingWithFile {
    class Print {
    class EnteringData {

    ✔ Správne

    class Employee {
    class EmployeeManager {
    class InvoiceItem {
    class FileDatabase {
    class UserInterface {
  • ✗ Nesprávne

    class employee
    class Employees
    class Invoiceitem
    class WorkingWithFile
    class Print
    class EnteringData

    ✔ Správne

    class Employee
    class EmployeeManager
    class InvoiceItem
    class FileDatabase
    class UserInterface
  • ✗ Nesprávne

    class employee {
    class Employees {
    class Invoiceitem {
    class WorkingWithFile {
    class Print {
    class EnteringData {

    ✔ Správne

    class Employee {
    class EmployeeManager {
    class InvoiceItem {
    class FileDatabase {
    class UserInterface {
  • ✗ Nesprávne

    class employee:
    class Employees:
    class invoice_item:
    class WorkingWithFile:
    class Print:
    class EnteringData:

    ✔ Správne

    class Employee:
    class EmployeeManager:
    class InvoiceItem:
    class FileDatabase:
    class UserInterface:
  • ✗ Nesprávne

    class employee {
    class Employees {
    class Invoiceitem {
    class WorkingWithFile {
    class Print {
    class EnteringData {

    ✔ Správne

    class Employee {
    class EmployeeManager {
    class InvoiceItem {
    class FileDatabase {
    class UserInterface {
  • ✗ Nesprávne

    class employee {
    class Employees {
    class Invoiceitem {
    class WorkingWithFile {
    class Print {
    class EnteringData {

    ✔ Správne

    class Employee {
    class EmployeeManager {
    class InvoiceItem {
    class FileDatabase {
    class UserInterface {
  • ✗ Nesprávne

    class employee {
    class Employees {
    class Invoiceitem {
    class WorkingWithFile {
    class Print {
    class EnteringData {

    ✔ Správne

    class Employee {
    class EmployeeManager {
    class InvoiceItem {
    class FileDatabase {
    class UserInterface {

Ak narazíte na program, kde sa trieda volá WorkingWithFile, jeho autor si pravdepodobne len vygooglil, že kód sa píše do class bez toho, aby tušil, že tým založil nejaký objekt.

Triedy v množnom čísle

V množnom čísle pomenovávame triedy len veľmi zriedka. Napríklad v Jave takto nájdeme triedu Arrays. Od tej nevytvárame inštancie a používame ju len pre prácu s inštanciami triedy Array, teda s poľami. Pole roztriedime napr. ako:

Arrays.sort(employees);

Osobne by mi dávalo väčší zmysel, aby tieto metódy mala na sebe priamo trieda Array a písali sme teda:

employees.sort()

Autori Javy pravdepodobne nechceli triedu Array príliš zložitú a tak pre niektoré metódy vytvorili túto druhú triedu. Výsledný prínos je diskutabilný. My triedy v množnom čísle väčšinou deklarovať nebudeme.

Pomenovanie tried v angličtine

Zdrojové kódy sú na ITnetwork rovnako ako reálne obchodné aplikácie po anglicky. Pre anglické názvy tried platí samozrejme to isté, čo sme si povedali vyššie. Môžeme však ľahko urobiť nasledujúce chyby:

  • Jednotné čísla - Keď v slovenčine pomenujeme triedu pracujúcu s autami SpravcaAut, mohol by sa ponúkať anglický preklad CarsManager. Správne je však CarManager, jednotné číslo, pretože Car tu funguje ako prídavné meno.
  • Poradie slov - Na rozdiel od slovenčiny je podstatné meno na konci súslovia, správca áut teda nie je ManagerCars alebo ManageCars, ale CarManager. Cesta k súboru nie je PathFile (čo by bol cestový súbor), ale FilePath a pod.

V angličtine sa pri triedach často používa koncovka -er, napr. TaskRunner, podľa toho, čo trieda robí.

Ukážme si zopár príkladov:

  • ✗ Nesprávne

    class CarsManager {
    class PathFile {
    class RunTasks {

    ✔ Správne

    class CarManager {
    class FilePath {
    class TaskRunner {
  • ✗ Nesprávne

    class CarsManager
    class PathFile
    class RunTasks

    ✔ Správne

    class CarManager
    class FilePath
    class TaskRunner
  • ✗ Nesprávne

    class CarsManager {
    class PathFile {
    class RunTasks {

    ✔ Správne

    class CarManager {
    class FilePath {
    class TaskRunner {
  • ✗ Nesprávne

    class CarsManager:
    class PathFile:
    class RunTasks:

    ✔ Správne

    class CarManager:
    class FilePath:
    class TaskRunner:
  • ✗ Nesprávne

    class CarsManager {
    class PathFile {
    class RunTasks {

    ✔ Správne

    class CarManager {
    class FilePath {
    class TaskRunner {
  • ✗ Nesprávne

    class CarsManager {
    class PathFile {
    class RunTasks {

    ✔ Správne

    class CarManager {
    class FilePath {
    class TaskRunner {
  • ✗ Nesprávne

    class CarsManager {
    class PathFile {
    class RunTasks {

    ✔ Správne

    class CarManager {
    class FilePath {
    class TaskRunner {

Pomenovanie atribútov

Atribúty sú "premenné" danej triedy. Pre ich pomenovanie teda platia tie isté zásady ako pre premenné, ktoré sme si už detailne vysvetľovali v lekcii Najčastejšie chyby programátorov - Vieš pomenovať premenné?.

Základným pravidlom opäť je, že atribúty pomenovávame podľa toho, čo je v nich uložené. Názov atribútu chápeme v kontexte názvu triedy a nemusí teda dávať zmysel sám o sebe. Z jazykového hľadiska sú názvy atribútov:

  • podstatné mená (name, employees...)
  • prídavné mená (disabled, sent...)

Pripomeňme si tu aj zvyšné zásady:

  • všetky atribúty pomenovávame buď po anglicky alebo po slovensky bez diakritiky, ale nie kombináciou týchto jazykov,
  • viacslovné atribúty pomenovávame pomocou notácie camelCase alebo snake_case v závislosti od jazyka,
  • ak atribút obsahuje kolekciu s viacerými hodnotami (napr. pole alebo List), je jeho názov v množnom čísle.

Ukážme si opäť nejaké príklady názvov atribútov tried:

  • ✗ Nesprávne

    private String Name;
    private boolean send;
    private String[] phonenumbers;
    private Button tlačidlo;
    private Address[] uzivatelAddress;

    ✔ Správne

    private String name;
    private boolean sent;
    private String[] phoneNumbers;
    private Button button;
    private Address[] userAddresses;
  • ✗ Nesprávne

    private string Name;
    private bool send;
    private string[] phonenumbers;
    private Button tlačidlo;
    private Address[] uzivatelAddress;

    ✔ Správne

    private string name;
    private bool sent;
    private string[] phoneNumbers;
    private Button button;
    private Address[] userAddresses;
  • ✗ Nesprávne

    private:
        string Name;
        bool send;
        string* phonenumbers;
        Button tlačidlo;
        Address* uzivatelAddress;

    ✔ Správne

    private:
        string name;
        bool sent;
        string* phoneNumbers;
        Button button;
        Address* userAddresses;
  • ✗ Nesprávne

    self._Name = ""
    self._send = False
    self._phonenumbers = []
    self._tlačidlo = Button()
    self._uzivatel_address = []

    ✔ Správne

    self._name = ""
    self._sent = False
    self._phone_numbers = []
    self._button = Button()
    self._user_addresses = []
  • ✗ Nesprávne

    private var Name: String
    private var send: Bool
    private var phonenumbers: [String]()
    private var tlačidlo: Button
    private var uzivatelAddress: [Address]()

    ✔ Správne

    private var name: String
    private var sent: Bool
    private var phoneNumbers: [String]()
    private var button: Button
    private var userAddresses: [Address]()
  • ✗ Nesprávne

    private string $Name;
    private bool $send;
    private array $phonenumbers;
    private Button $tlačidlo;
    private array $uzivatelAddress;

    ✔ Správne

    private string $name;
    private bool $sent;
    private array $phoneNumbers;
    private Button $button;
    private array $userAddresses;
  • ✗ Nesprávne

    this._Name = "";
    this._send = false;
    this._phonenumbers = [];
    this._tlačidlo = new Button();
    this._uzivatelAddress = [];

    ✔ Správne

    this._name = "";
    this._sent = false;
    this._phoneNumbers = [];
    this._button = new Button();
    this._userAddresses = [];

Pomenovanie metód a parametrov

Metódy označujú deje, ich názov obsahuje teda sloveso! Môže ísť o:

  • prikazovací tvar (load(), setId()) - Metóda prevažne vykonáva nejakú činnosť a jej výsledok môže alebo nemusí vracať. Nevolíme infinitív alebo -ing tvar, napr. loading().
  • opytovací tvar - Metódou sa prevažne pýtame na nejakú hodnotu, než aby sme chceli vykonať nejakú akciu (napr. getRank() alebo isDisabled() pre hodnotu typu boolean). Už vieme, že takýmto metódam hovoríme gettery.
  • V prípade viacerých slov ich vo väčšine jazykov pomenovávame podľa camelCase, v Pythone podľa snake_case. V C# začínajú metódy veľkým písmenom.

Metódy pomenovávame podľa toho, čo robia! Vyhýbame sa neurčitým názvom ako work(), action(), run() a pod.

Ukážme si príklady:

  • ✗ Nesprávne

    public void printing(Employee employee) {
    public boolean getEnabled() {
    private void data() {
    public void work() {

    ✔ Správne

    public void printInfo(Employee employee) {
    public boolean isEnabled() {
    private void generateData() {
    public void importBackup() {
  • ✗ Nesprávne

    public void Printing(Employee employee)
    public bool GetEnabled()
    private void Data()
    public void Work()

    ✔ Správne

    public void PrintInfo(Employee employee)
    public bool IsEnabled()
    private void GenerateData()
    public void ImportBackup()
  • ✗ Nesprávne

    private:
        void data() {
    
    public:
        void printing(Employee employee) {
        bool getEnabled() {
        void work() {

    ✔ Správne

    private:
        void generateData() {
    
    public:
        void printInfo(Employee employee) {
        bool isEnabled() {
        void importBackup() {
  • ✗ Nesprávne

    def printing(employee):
    def get_enabled():
    def _data():
    def work():

    ✔ Správne

    def print_info(employee):
    def is_enabled():
    def _generate_data():
    def import_backup():
  • ✗ Nesprávne

    func printing(employee: Employee) {
    func getEnabled() -> Bool {
    private func data() {
    func work() {

    ✔ Správne

    func printInfo(employee: Employee) {
    func isEnabled() -> Bool {
    private func generateData() {
    func importBackup() {
  • ✗ Nesprávne

    public function printing(Employee $employee): void {
    public function getEnabled(): bool {
    private function data(): void {
    public function work(): void {

    ✔ Správne

    public function printInfo(Employee $employee): void {
    public function isEnabled(): bool {
    private function generateData(): void {
    public function importBackup(): void {
  • ✗ Nesprávne

    printing(employee) {
    getEnabled() {
    _data() {
    work() {

    ✔ Správne

    printInfo(employee) {
    isEnabled() {
    _generateData() {
    importBackup() {

Parametre metód

Parameter metódy je premenná, a preto pre ich názvy platia tie isté pravidlá ako pre premenné a atribúty (napríklad nikdy nepomenujeme parameter param 🙂). Je tu však jedna dôležitá vec na zváženie, a to je použitie dvojitej negácie. Ukážme si posledný príklad:

  • ✗ Nesprávne

    public void importData(boolean disableForeignKeys) {
    
    importData(false);

    ✔ Správne

    public void importData(boolean enableForeignKeys) {
    
    importData(true);
  • ✗ Nesprávne

    public void ImportData(bool disableForeignKeys = false)

    ✔ Správne

    public void ImportData(bool enableForeignKeys = true)
  • ✗ Nesprávne

    public:
        void importData(bool disableForeignKeys = false) {

    ✔ Správne

    public:
        void importData(bool enableForeignKeys = true) {
  • ✗ Nesprávne

    def import_data(disable_foreign_keys = False):

    ✔ Správne

    def import_data(enable_foreign_keys = True):
  • ✗ Nesprávne

    func importData(disableForeignKeys: Bool = false) {

    ✔ Správne

    func importData(enableForeignKeys: Bool = true) {
  • ✗ Nesprávne

    public function importData(bool $disableForeignKeys = false): void {

    ✔ Správne

    public function importData(bool $enableForeignKeys = true): void {
  • ✗ Nesprávne

    importData(disableForeignKeys = false) {

    ✔ Správne

    importData(enableForeignKeys = true) {

Kto z vás dokáže povedať, či sú v prvom variante bez uvedenia parametra (pre Javu s odovzdaním false) povolené cudzie kľúče? Všetko je zas o ľudskom mozgu, ktorý nie je zvyknutý fungovať s dvojitou negáciou. Volíme teda skôr druhý variant.

V budúcej lekcii, Najčastejšie chyby programátorov - Podmienky, si ukážeme najčastejšie chyby začiatočníkov pri pomenovávaní kolekcií, boolean výrazov a DRY.


 

Predchádzajúci článok
Najčastejšie chyby programátorov - Vieš pomenovať premenné?
Všetky články v sekcii
Best practices pre návrh softwaru
Preskočiť článok
(neodporúčame)
Najčastejšie chyby programátorov - Podmienky
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
216 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity