Az OTRS projekt következetes fejlesztésének megtartása érdekében irányelveket fektettünk le a stílusra vonatkozóan a különböző programnyelvekhez.
TABULÁTOR: 4 szóközt használunk. Példa a zárójelekre:
if ($Feltétel) { Izé(); } else { Bigyó(); } while ($Feltétel == 1) { Izé(); }
A sorok általában nem lehetnek hosszabbak 120 karakternél, hacsak ez különleges okok miatt nem szükséges.
A jobb olvashatóság érdekében szóközöket használunk a kulcsszavak és a nyitó zárójelek között.
if ()... for ()...
Ha csak egy egyedülálló változó van, akkor a zárójelek belül szóközök nélkül veszik körbe a változót.
if ($Feltétel) { ... } # e helyett if ( $Feltétel ) { ... }
Ha a feltétel nem csak egy egyedülálló változó, akkor szóközöket használunk
a zárójelek és a feltétel között. És továbbra is szóköz van a kulcsszó
(például if
) és a nyitó zárójel között.
if ( $Feltétel && $ABC ) { ... }
Ne feledje, hogy a Perl beépített függvényeinél nem használunk zárójeleket:
chomp $Variable;
Csatolja hozzá a következő fejlécet minden egyes forrásfájlhoz. A forrásfájlok UTF-8 karakterkódolással vannak elmentve.
# -- # (file name) - a short description what it does # Copyright (C) 2001-2018 OTRS AG, https://otrs.com/ # -- # This software comes with ABSOLUTELY NO WARRANTY. For details, see # the enclosed file COPYING for license information (GPL). If you # did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. # --
A végrehajtható fájloknak (*.pl
) különleges fejlécük
van.
#!/usr/bin/perl # -- # (file name) - a short description what it does # Copyright (C) 2001-2018 OTRS AG, https://otrs.com/ # -- # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see https://www.gnu.org/licenses/gpl-3.0.txt. # --
A feltételek meglehetősen összetettek lehetnek, és lehetnek „láncolt” feltételek is (logikai „és” vagy „vagy” operátorral összekapcsolva). Az OTRS kódolásakor tisztában kell lennie számos helyzettel.
A bevált Perl gyakorlatok azt mondják, hogy a magas precedenciájú
operátorokat (&&
és ||
) nem
kellene keverni az alacsony precedenciájú operátorokkal
(and
és or
). A zűrzavar elkerülése
érdekében mindig a magas precedenciájú operátorokat használjuk.
if ( $Condition1 && $Condition2 ) { ... } # e helyett if ( $Condition and $Condition2 ) { ... }
Ez azt jelenti, hogy tisztában kell lennie a buktatókkal. Néha zárójeleket kell használnia, hogy világossá tegye, mit szeretne.
Ha hosszú feltételei vannak (a sor 120 karakternél hosszabb), akkor több
sorra kell tördelnie azt. Továbbá a feltételek kezdete egy új sorban van
(nem az if
sorában).
if ( $Feltétel1 && $Feltétel2 ) { ... } # e helyett: if ( $Feltétel1 && $Feltétel2 ) { ... }
Jegyezze meg azt is, hogy a jobboldali zárójel egyedül áll a sorban,
valamint a baloldali kapcsos zárójel szintén új sorban van, és ugyanolyan
behúzással rendelkezik mint az if
. Az operátorok egy új
sor elején vannak! A következő példák bemutatják, hogyan kell ezt csinálni…
if ( $XMLHash[0]->{otrs_stats}[1]{StatType}[1]{Content} && $XMLHash[0]->{otrs_stats}[1]{StatType}[1]{Content} eq 'static' ) { ... } if ( $TemplateName eq 'AgentTicketCustomer' ) { ... } if ( ( $Param{Section} eq 'Xaxis' || $Param{Section} eq 'All' ) && $StatData{StatType} eq 'dynamic' ) { ... } if ( $Self->{TimeObject}->TimeStamp2SystemTime( String => $Cell->{TimeStop} ) > $Self->{TimeObject}->TimeStamp2SystemTime( String => $ValueSeries{$Row}{$TimeStop} ) || $Self->{TimeObject}->TimeStamp2SystemTime( String => $Cell->{TimeStart} ) < $Self->{TimeObject}->TimeStamp2SystemTime( String => $ValueSeries{$Row}{$TimeStart} ) ) { ... }
Általánosan azért használunk „hátul álló if
”
utasításokat, hogy csökkentsük a szintek számát. De ne használjuk többsoros
utasításoknál, és csak akkor megengedett, amikor visszatérési utasításokat
hoz magával a függvény, vagy egy ciklus befejezéséhez, illetve a következő
iterációra való ugráshoz.
Ez helyes:
next ITEM if !$ItemId;
Ez hibás:
return $Self->{LogObject}->Log( Priority => 'error', Message => 'ItemID szükséges!', ) if !$ItemId;
Ez kevésbé karbantartható ennél:
if( !$ItemId ) { $Self->{LogObject}->Log( ... ); return; }
Ez helyes:
for my $Needed (1..10) { next if $Needed == 5; last if $Needed == 9; }
Ez hibás:
my $Var = 1 if $Something == 'Yes';
A Perl néhány beépített szubrutinját nem lehet használni semmilyen helyen:
Ne használja a die
és exit
szubrutinokat a .pm
fájlokban.
Ne használja a Dumper
függvényt a kiadott fájlokban.
Ne használja a print
utasítást a .pm
fájlokban.
Ne használja a require
kulcsszót, inkább használja a
Main::Require()
metódust.
Használja a TimeObject
függvényeit az olyan beépített
függvények helyett, mint például a time()
,
localtime()
, stb.
A reguláris kifejezéseknél mindig kapcsos zárójelekkel használjuk az
m//
operátort elválasztóként. Használjuk az
x
, m
és s
módosítókat is. Az x
módosítók lehetővé teszik a
reguláris kifejezések megjegyzéssel történő ellátását, és szóközök
használatát a logikai csoportok „csoportosításához”.
$Date =~ m{ \A \d{4} - \d{2} - \d{2} \z }xms $Date =~ m{ \A # a szöveg kezdete \d{4} - # év \d{2} - # hónap [^\n] # minden, kivéve az új sort #.. }xms;
Mivel a szóköznek többé nincs különleges jelentése, ezért egy egyedüli
karakterosztályt kell használnia egy egyedülálló szóköz illesztéséhez
([ ]
). Ha akármennyi szóközre szeretne illeszteni, akkor
azt a \s
használatával teheti meg.
A reguláris kifejezésben a pont (.
) tartalmazza az új
sort (minthogy az s
módosító nélküli reguláris
kifejezésben a pont azt jelenti, hogy „minden, kivéve az új sor”). Ha
bármire szeretne illeszteni az új sort kivéve, akkor a tagadott egyedüli
karakterosztályt kell használnia ([^\n]
).
$Text =~ m{ Teszt [ ] # itt szóköznek kell lennie a „Teszt” és a „Regex” között Regex }xms;
A neveket és a megjegyzéseket angolul kell írni. A változókat, objektumokat és metódusokat leíró főnevekkel vagy főnévi igenevekkel írjuk úgy, hogy az első betű nagybetűs legyen (CamelCase).
A neveknek annyira leírónak kell lenniük, amennyire csak lehetséges. Az
olvasónak egy név alapján meg kell tudni mondania, hogy az mit jelent
anélkül, hogy túl mélyre ásná magát a kódban. Például használja a
$ConfigItemID
nevet az $ID
helyett. Példák: @TicktIDs
, $Output
,
StateSet()
, stb.
Ha több változója van, akkor deklarálhatja azokat egyetlen sorban, ha azok „összetartoznak”:
my ($Minute, $Hour, $Year);
Egyébként tördelje azokat külön sorokba:
my $Minute; my $ID;
Ne állítson be undef
vagy ''
kezdeti
értéket a deklarációban, ugyanis ez elrejtheti a hibákat a kódban.
my $Variable = undef; # ugyanaz mint my $Variable;
Akkor állíthat be egy változót ''
értékre, ha szövegeket
szeretne összefűzni:
my $SqlStatement = ''; for my $Part ( @Parts ) { $SqlStatement .= $Part; }
Egyébként „előkészítetlen” figyelmeztetést kaphat.
A szubrutinoknak átadott paraméterek lekéréséhez az OTRS normális esetben a
%Param
kivonatot használja (nem a
%Params
kivonatot). Ez jobban olvasható kódot eredményez,
mivel minden esetben tudjuk, hogy amikor %Param
kivonatot
használjuk a szubrutin kódokban, akkor paraméterkivonat került átadásra a
szubrutinnak.
Csak néhány kivételnél kell a paraméterek szabályos listáját használni. Így el szeretnénk kerülni az ehhez hasonlókat:
sub TestSub { my ( $Self, $Param1, $Param2 ) = @_; }
Inkább ezt szeretnénk használni:
sub TestSub { my ( $Self, %Param ) = @_; }
Ennek számos előnye van: nem kell megváltoztatnunk a kódot a szubrutinban, amikor egy új paramétert kell átadni, és egy elnevezett paraméterekkel rendelkező függvény hívása sokkal olvashatóbb.
Ha egy függvényhívás egynél több elnevezett paramétert igényel, akkor tördelje azokat több sorba:
$Self->{LogObject}->Log( Priority => 'error', Message => "Need $Needed!", );
E helyett:
$Self->{LogObject}->Log( Priority => 'error', Message => "Need $Needed!", );
A szubrutinoknak rendelkezniük kell egy return
utasítással. Az explicit return
utasítás előnyben
részesített az implicit módszernél (az utolsó utasítás eredménye a
szubrutinban), mivel ez tisztázza, hogy mit ad vissza a szubrutin.
sub TestSub { ... return; # undef visszaadása, de nem az utolsó utasítás eredménye }
Az explicit visszatérési értékek azt jelentik, hogy nem kell egy
return
utasítást tenni egy szubrutinhívást követően.
return $Self->{DBObject}->Do( ... );
A következő példa jobb, mivel ez explicit módon megmondja, hogy mi kerül
visszaadásra. A fenti példával az olvasó nem tudja, hogy mi a visszatérési
érték, mivel nem tudhatja, hogy a Do()
mit ad vissza.
return if !$Self->{DBObject}->Do( ... ); return 1;
Ha egy szubrutin eredményét hozzárendeli egy változóhoz, akkor egy „jó” változónév jelzi, hogy mi lett visszaadva:
my $SuccessfulInsert = $Self->{DBObject}->Do( ... ); return $SuccessfulInsert;
A use strict
és use warnings
utasításoknak kell az első két „use”-nak lennie a modulban. Ez helyes:
package Kernel::System::ITSMConfigItem::History; use strict; use warnings; use Kernel::System::User; use Kernel::System::Time;
Ez hibás:
package Kernel::System::ITSMConfigItem::History; use Kernel::System::User; use Kernel::System::Time; use strict; use warnings;
Az OTRS-ben sok objektum érhető el. De nem kell minden egyes objektumot használnia minden fájlban az előtétprogram/háttérprogram elválasztásának megtartásához.
Ne használja a LayoutObject
objektumot az alapmodulokban
(Kernel/System
).
Ne használja a ParamObject
objektumot az alapmodulokban
(Kernel/System
).
Ne használja a DBObject
objektumot az előtétprogram
modulokban (Kernel/Modules
).
A szubrutinokat mindig dokumentálni kell. A dokumentum tartalmaz egy általános leírást arról, hogy mit csinál a szubrutin, egy minta szubrutinhívást, és hogy mit ad vissza a szubrutin. Ezeknek ebben a sorrendben kell lenniük. Egy minta dokumentáció így néz ki:
=item LastTimeObjectChanged() calculates the last time the object was changed. It returns a hash reference with information about the object and the time. my $Info = $Object->LastTimeObjectChanged( Param => 'Value', ); This returns something like: my $Info = { ConfigItemID => 1234, HistoryType => 'foo', LastTimeChanged => '08.10.2009', }; =cut
Lemásolhat és beilleszthet egy Data::Dumper
kimenetet a
visszatérési értékekhez.
Általánosságban meg kell próbálni olvashatóan és önmagát magyarázóan írni a kódot, amennyire csak lehetséges. Ne írjon megjegyzést annak magyarázásához, hogy a nyilvánvaló kód mit csinál, mert az szükségtelen megkettőzés. A jó megjegyzéseknek azt kell elmagyarázniuk, hogy miért van valami a kódban, mik a lehetséges mellékhatások és bármi egyéb, amely különleges lehet vagy szokatlanul bonyolult a kóddal kapcsolatban.
Ragaszkodjon a következő irányelvekhez:
Mindig vonzóbb a kódot úgy írni, hogy nagyon olvasható és önmagát magyarázó legyen, például pontos változónevekkel és függvénynevekkel.
Ne ismételjen (nyilvánvaló) kódot a magyarázatokban.
# HIBÁS: # beállítási objektum lekérése my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
Általában a kódmagyarázatoknak a kód célját kellene elmagyarázniuk, és nem azt, hogy részletesen hogyan működik. Lehetnek kivételek különösen bonyolult kódnál, de ebben az esetben egy átszerkesztés lenne dicséretes, hogy olvashatóbb legyen.
Mindent dokumentálni kell, ami nem világos, furfangos vagy amit összerakott a fejlesztés során.
Mindig teljes mondatokat használjon (első betűt nagybetűvel írva és központozással). Egy mondat következő sorait be kell húzni.
# Annak ellenőrzése, hogy meg lett-e adva objektumnév. if ( !$_[1] ) { $_[0]->_DieWithError( Error => "Hiba: hiányzó paraméter (objektumnév)", ); } # Az objektum rögzítése, amelyet lekérni készülünk, hogy potenciálisan jobb # hibaüzenetet készíthessünk. # Utasításmódosító „if”-nek kell lennie, különben a „local” helyi lesz az # „if”-blokk hatóköréhez képest. local $CurrentObject = $_[1] if !$CurrentObject;
Ez lehet vagy teljes mondat (nagy kezdőbetű és központozás), vagy csak egy kifejezés (kis kezdőbetű és nincs központozás).
$BuildMode = oct $Param{Mode}; # oktális *típusról*, nem oktális *típusra* # vagy $BuildMode = oct $Param{Mode}; # Átalakítás oktális *típusról*, nem oktális *típusra*.
Ha nincs esély az SQL-utasítás megváltoztatására, akkor azt a
Prepare
függvényben kell használni. Ennek az az oka, hogy
az SQL-utasítás és a kötési paraméterek közelebb vannak egymáshoz.
Az SQL-utasítást egy összefűzések nélküli, pontosan behúzott szövegként kell megírni úgy, mint például ezt:
return if !$Self->{DBObject}->Prepare( SQL => ' SELECT art.id FROM article art, article_sender_type ast WHERE art.ticket_id = ? AND art.article_sender_type_id = ast.id AND ast.name = ? ORDER BY art.id', Bind => [ \$Param{TicketID}, \$Param{SenderType} ], );
Ezt könnyű olvasni és módosítani, és az üres karaktereket jól tudják kezelni
a támogatott DBMS-ek. Az automatikusan előállított SQL-kódnál (mint a
TicketSearch
modulban) ez a behúzás nem szükséges.
Valahányszor adatbázis-függvényeket használ, kezelnie kell a hibákat. Ha valami elromlik, az visszakerül a szubrutinból:
return if !$Self->{DBObject}->Prepare( ... );
Használja a Limit => 1
korlátozást, ha csak egyetlen sort
vár visszatérésként.
$Self->{DBObject}->Prepare( SQL => 'SELECT id FROM users WHERE username = ?', Bind => [ \$Username ], Limit => 1, );
Az összes JavaScript betöltődik minden böngészőben (nincsenek böngésző trükközések a sablonfájlokban). A kód felelős annak eldöntéséért, hogy ki kell hagynia vagy végre kell hajtania saját magának bizonyos részeit az egyes böngészőkben.
Könyvtárszerkezet a js/
mappán belül:
* js * thirdparty # harmadik féltől származó függvénykönyvtárak, * ckeditor-3.0.1 # amelyek mindig tartalmaznak verziószámot a * jquery-1.3.2 # könyvtáron belül * Core.Agent.* # az ügyintézői felületre jellemző dolgok * Core.Customer.* # ügyfélfelület * Core.* # közös API
A változóneveket CamelCase jelölésrendszerben kell írni, akárcsak a Perlben.
A jQuery objektumot tartalmazó változókat $
karakterrel
kell kezdeni, például: $Tooltip
.
A Perl-kód magyarázási irányelvei a JavaScriptre is vonatkoznak.
Egysoros megjegyzéseket //
karakterekkel kell készíteni.
Hosszabb megjegyzéseket /* ... */
karakterekkel kell
készíteni.
Ha megjegyzésre állítja a JavaScript kód egyes részeit, akkor csak a
//
karaktereket használja, ugyanis a /*
... */
használata problémákat okozhat a reguláris kifejezéseknél a
kódban.
Mindig a $.bind()
függvényt használja a jQuery rövidített
nevű eseménymetódusai helyett a jobb olvashatóságért (hibás:
$SomeObject.click(...)
, helyes:
$SomeObject.bind('click', ...
).
Ne használja a $.live()
függvényt! Súlyos
teljesítményproblémáink voltak a $.live()
függvénnyel az
egéreseményekkel összefüggésben. Ne használja, amíg nem ellenőrizhető, hogy
a $.live()
problémák nélkül működik a többi
eseménytípussal.
Ha eseményeket köt a $.bind()
függvénnyel, akkor
győződjön meg arról, hogy korábban leválasztotta azokat az
$.unbind()
használatával annak biztosításához, hogy az
események ne legyenek kétszer kötve, ne kelljen a kódot még egy alkalommal
végrehajtani.
A legkisebb felbontás 1024×768 képpont.
Az elrendezés folyékony, amely azt jelenti, hogy ha a képernyő szélesebb, akkor a helyet fel fogja használni.
Az abszolút méretmeghatározásokat képpontban (px) kell megadni, hogy következetes kinézetet kapjon a legtöbb platformon és böngészőben.
A dokumentáció CSSDOC használatával készül (nézze meg a CSS-fájlokat példaként). Az összes logikai blokknak rendelkeznie kell egy CSSDOC megjegyzéssel.
Az objektumorientált CSS megközelítést követjük. Lényegében ez azt jelenti, hogy az elrendezés különböző általános építőkockák egyesítésével érhető el egy bizonyos látványterv megvalósításához.
Ahol csak lehetséges, nem szabad a modulra jellemző látványtervet
használni. Például ezért nem dolgozunk azonosítókkal a
body
elemen sem, ha az elkerülhető.
Az összes meghatározásnak ugyanabban a sorában van a {
karakter mint a kiválasztó, az összes szabály szabályonként egy sorban van
meghatározva, a meghatározások egyetlen }
karaktert
tartalmazó sorral végződnek. Nézze meg a következő példát:
#Selector { width: 10px; height: 20px; padding: 4px; }
A :
és szabály értéke között van egy szóköz.
Minden szabály 4 szóközzel van behúzva.
Ha több kiválasztó van megadva, akkor vesszővel válassza el azokat, és mindegyiket tegye külön sorba:
#Selector1, #Selector2, #Selector3 { width: 10px; }
Ha a szabályok egyesíthetők, akkor egyesítse azokat (például egyesítse a
background-position
, background-image
,
stb. szabályokat a background
szabályba).
A szabályoknak logikai sorrendben kell lenniük egy meghatározáson belül (az összes színre jellemző szabály együtt, az összes pozicionáló szabály együtt, stb.).
Az összes azonosító és név CamelCase jelölésrendszerben van írva:
<div class="NavigationBar" id="AdminMenu"></div>