WebHU - Programozási kérdések és válaszok

ReSharper és StyleCop kontra lelépési szabály (tiszta kód)

Elképzelem, hogy ez egy kicsit megosztó poszt lehet, de egy ideje nehezen tudom megfogalmazni, és szeretném a szélesebb fejlesztői közösség elé tárni.

Olyan szerepkörben dolgozom, ahol a fájl ellenőrzése előtt futtatjuk a ReSharper automatikus formázási eszközt, amely hozzáférésmódosító szerint csoportosítja a dolgokat régiókba, és ábécé sorrendbe rendezi a benne lévő tagokat. Alapvetően az ebben a bejegyzésben leírt osztályelrendezési mintát követi: ábécésítési módszerek a Visual Studio-ban a>, amit úgy tűnik, az emberek nagyon szeretnek.

Bármilyen kódolási szabvány mellett szívesen dolgozom, de nehezen tudom összeegyeztetni ezt a megközelítést a tiszta kód írásával, elsősorban azért, mert szigorúan betartom a lelépési szabályt (Robert C Martin – Clean Code), és Az abc-sorolás megtöri azt.

A lelépési szabály leírása a következő:

Szeretnénk, ha a kód felülről lefelé haladó narratívaként olvasható. Szeretnénk, ha minden függvényt követnének az absztrakció következő szintjén lévők, hogy a függvények listáját leolvasva egy absztrakciós szintről lefelé tudjunk olvasni a programot. Ezt nevezem lelépési szabálynak. Egy függvény argumentumainak ideális száma nulla. Következik egy. Aztán kettő. A három érvet lehetőleg kerülni kell.

Ezt a megközelítést követve a következő (kitalált) kódot írhatom:

public class Processor
{
    public Processor(ProcessData data)
    {
        Configure(data);
    }


    public void Configure(ProcessData data)
    {
        ClearState();
        UnpackData();
        ProcessData();
        TransformData();
        PostProcessData();
    }

    private void ClearState() { /*Snip*/ }

    private void UnpackData() { /*Snip*/ }

    private void ProcessData() { /*Snip*/ }

    private void TransformData() { /*Snip*/ }

    private void PostProcessData() { /*Snip*/ }


    public IEnumerable<GroupedRecordSet> AggregateRecords(IEnumerable<Record> records)
    {
        var groups = CalculateGrouping(records);
        PopulateGroups(groups, records);
        return groups;
    }

    private IEnumerable<GroupedRecordSet> CalculateGrouping(IEnumerable<Record> records) { /*snip*/ }

    private void PopulateGroups(IEnumerable<GroupedRecordSet> groups, IEnumerable<Record> records) { /*snip*/ }
}

Aztán az automatikus formázás futtatásakor a következőket nézem (a megjegyzések eltávolítva):

public class Processor
{
    #region Constructors and Destructors

    public Processor(ProcessData data)
    {
        Configure(data);
    }

    #endregion

    #region Public Methods and Operators

    public IEnumerable<GroupedRecordSet> AggregateRecords(IEnumerable<Record> records)
    {
        var groups = this.CalculateGrouping(records);
        this.PopulateGroups(groups, records);
        return groups;
    }

    public void Configure(ProcessData data)
    {
        this.ClearState();
        this.UnpackData();
        this.ProcessData();
        this.TransformData();
        this.PostProcessData();
    }

    #endregion

    #region Methods

    private IEnumerable<GroupedRecordSet> CalculateGrouping(IEnumerable<Record> records) { /*snip*/ }

    private void ClearState() { /*snip*/ }

    private void PopulateGroups(IEnumerable<GroupedRecordSet> groups, IEnumerable<Record> records) { /*snip*/ }

    private void PostProcessData() { /*snip*/ }

    private void ProcessData() { /*snip*/ }

    private void TransformData() { /*snip*/ }

    private void UnpackData() { /*snip*/ }

    #endregion
}

A második stílust most egy pillantásra sokkal nehezebb megérteni, és azon kapom magam, hogy szokatlanul sok mindent meg kell őriznem az első stílus olvashatóságának megőrzése érdekében, a második korlátain belül. Ezek tartalmazzák:

  • Tulajdonos metódusnév előtagja – azaz ConfigureClearState, ConfigureUnpackData, AggregateRecordsCalculateGroupings, AggregateRecordsPopulateGroups stb. Ez hosszú tagnevekhez vezet, különösen, ha a 'owner' metódusok további saját metódusokat igényelnek.
  • Defaktorálás – a kód áthelyezése kis metódusokból, amelyeket eredetileg újra faktoráltam, vissza arra a metódusra, ahonnan jött. Ami hosszú módszerekhez vezet.
  • Részleges osztályok – Igazából még nem jutottam el idáig, de teljesen lehetséges, hogy a kapcsolódó metódusokat részleges osztályokba fogom helyezni, hogy elkülönüljenek a fő kódtörzstől. Ami megtölti a megoldásböngészőt kódfájlok halomával.

Nyilvánvalóan nem vagyok elégedett ezen megközelítések egyikével sem, de amennyire én látom, ez az egyetlen igazi lehetőség az olvashatóság fenntartására a működési paramétereken belül.

Úgy tűnik, a második megközelítés a Microsoft house stílusa, így azt hiszem, a kérdésem(ek) a következők lennének:

  • Helyes, hogy a második megközelítés a Microsoft ház stílusa?
  • Ha igen, hogyan tartja fenn a Microsoft tiszta olvasható kódot a második stílusban?
  • Találkozott már valaki ezzel az eltéréssel, és milyen megközelítéseket alkalmaztak az emberek a jó olvashatóság elérése érdekében?
  • Melyek a tiszta kód írásának általános stíluspreferenciái?

Találtam egy példányt a Microsoft kódolási stílusából: http://blogs.msdn.com/b/brada/archive/2005/01/26/361363.aspx


Válaszok:


1

A Robert Martin megközelítés az olvashatóságot célozza meg. Az előnyök teljes kihasználásához további konvenciókat vagy szabályokat kell alkalmaznia (pl. elnevezés, megjegyzések elhagyása értelmes és leíró nevek kiválasztása érdekében, egyetlen felelősség, rövid módszerek stb.). Ezután a kódot úgy olvashatja, mint egy általános szöveges dokumentumot. Ha a következő absztrakciós szintű funkcióblokk behúzása javítja az olvashatóságot is. Így fejezheti ki az absztrakciós szinteket a kódformátumával:

public void Level1Member()
{
    RunLevel2Member();
    RunAnotherLevel2Member();
}

    private void RunLevel2Member()
    {
        RunLevel3Member();
    }

        private void RunLevel3Member()
        {
            //....
        }

    private void RunAnotherLevel2Member()
    {
        //..
    }

Lehet, hogy visszaél az egérgörgővel, amikor az ábécé stílust csak azért használja, hogy felfelé és lefelé görgessen, hogy megtalálja a kontextust. Másrészt nem kell fenntartania a behúzásokat és az absztrakciós szinteket a kód átalakítása során.

Ez két különböző megközelítés, különböző célokkal. Az egyik szereti javítani az olvashatóságot (ember számára), és lehetővé teszi a metódusok megtalálását a programfolyamat alapján, míg a másik azt szereti, ha a nevük alapján gyorsan megtalálja a metódusokat. Az ábécé szerinti rendezés támogatja azt az elterjedt konvenciót, hogy az összes nyilvános metódust egybe kell helyezni, ami szintén növeli az osztály céljának és viselkedésének kiderítésének esélyét (egy pillantással). A Step-down boldogan keveri a nyilvános és a magán módszereket, más célt követve.

Nem lehet mindkettő. Tehát semmi esetre se sérts meg több száz szabályt, és ne hagyd ki a refaktorálást, csak hogy összekevered ezt a két stílust. Semmi értelme, és sokkal kevésbé olvashatóvá teszi a kódot.

Ha úgy gondolja, hogy a lefelé mutató stílus olvasása kényelmesebb és természetesebb, mint a kód szótári stílusban történő olvasása, használja azt. én igen.

Soha nem hallottam a Microsoft belső konvencióiról, mint például a kódok ábécé szerinti rendezése. A hivatalos .NET-konvenció nem céloz egy szervezetet vagy egyezményt a kód felépítésére vonatkozóan (amellett, hogy javasolja, hogy az esemény delegáltját helyezzék az osztály tetejére stb.).

A lelépési szabály csak egy nem hivatalos stílus. Egyes automatikus formázó eszközök nem támogatják a behúzási módszereket, és visszahelyezik őket egy szintre.

Mellesleg, a részleges osztályok használata a rossz tervezés elfedésére (túl nagy osztályok/túl nagy felelősség) nem lehetséges annak, aki törődik a tiszta és karbantartható kóddal.

Hogy megkönnyítsem a dolgodat, megpróbálom megmutatni a csapatodnak a stílusod előnyeit, vagy elfogadni azt a stílust, amelyet a csapatod többsége kedvel.

Ne felejtse el, hogy az IDE nagyon jól segít Önnek abban, hogy kiemeli a metódusokat a kódban, vagy olyan funkciókat biztosít, mint a „megvalósítás” vagy a „használatok keresése”, vagy a metódushívások sorrendjét mutató kódleképezés. És vannak sokkal fontosabb szabályok a kód olvashatóságával kapcsolatban, mint például a jó nevek és a jó tervezés.

Igen, de én személy szerint jobban szeretem a visszalépést.

20.02.2014
  • Egyetértek, és az ábécé szerinti rendezést is elég feleslegesnek tartom, mivel már számos olyan helyünk van az IDE-ben, ahol ábécé sorrendben elérhetjük a tagokat, és egyenesen hozzájuk ugorhatunk. 20.02.2014
  • Azt sem tudom, hogy mit gondolok a kód behúzásáról, hogy a lépéseket fizikaivá tegyem, mindig is hajlamos voltam a metódusutasítások logikai csoportjait kettős fehér vonallal elválasztani. 20.02.2014
  • Igen, ízlés szerint. Úgy gondolom, hogy az oldal görgetése során könnyebb meghatározni a behúzás változását, mint a sorköz (1 sor) különbségét, csak hogy megtudja, hol van a kódban. Ismeretes, hogy több szóköz a sorok között kényelmetlen olvasni (szemmozgás). A behúzás jobban láthatóvá teszi az absztrakciós szinteket. Az ötlet az, hogy csak el kell olvasnia az első szintet (nem behúzott) és talán a második szintű metódusokat, hogy megértse a kód alapvető funkcióját. Minden további behúzás vagy absztrakciós szint több részletet tár fel az adott osztály alapvető funkcióinak megvalósítására vonatkozóan. 20.02.2014
  • A lelépési szabály nem lehetséges azokon a nyelveken, amelyek megkövetelik vagy javasolják, hogy a ba függvényt deklarálják használat előtt. Azaz javascript. 26.12.2015
  • @Ray, mint a C/C++-ban, van deklarációd és definíciód. A fordítónak tudnia kell a definíciókról, MIELŐTT ténylegesen használni tudná őket. A nyilatkozatnak nincs törzse. Ez benne van a deklarált függvény definíciójában. Ebben az esetben csak az összes deklarációt egy helyen kell tartania (például fejlécfájlban), és át kell helyeznie a definíciókat a forrásfájlba. Mindkét fájlban rendezheti és rendezheti a preferenciáit. JavaScriptet nevezted el. A JavaScript csak a „deklarációt” ismeri, ami olyan, mint a C/C++ definíciója. A JavaScript (mint például a Java, C#) lehetővé teszi, hogy tetszőleges sorrendben tetszőleges helyen „definíciókat” helyezzen el. 29.12.2015
  • @Ray, gondolom a továbbítási nyilatkozatra hivatkozol. 29.12.2015
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..