Sdílet prostřednictvím


Refaktoring do čistých funkcí (LINQ to XML)

Důležitým aspektem čistě funkčních transformací je naučit se refaktorovat kód pomocí čistých funkcí.

Poznámka:

Běžnou nomenklaturou funkčního programování je, že refaktorujete programy pomocí čistých funkcí. V jazyce Visual Basic a C++ je to v souladu s používáním funkcí v příslušných jazycích. V jazyce C# se však funkce nazývají metody. Pro účely této diskuze je čistá funkce implementována jako metoda v jazyce C#.

Jak jsme uvedli dříve v této části, čistá funkce má dvě užitečné vlastnosti:

  • Nemá žádné vedlejší účinky. Funkce nemění žádné proměnné ani data jakéhokoli typu mimo funkci.
  • Je konzistentní. Vzhledem ke stejné sadě vstupních dat se vždy vrátí stejná výstupní hodnota.

Jedním ze způsobů přechodu na funkční programování je refaktoring stávajícího kódu, který eliminuje zbytečné vedlejší účinky a externí závislosti. Tímto způsobem můžete vytvořit čisté verze funkce existujícího kódu.

Tento článek popisuje, co je čistá funkce a co ne. Kurz : Manipulace s obsahem v dokumentu WordprocessingML ukazuje, jak manipulovat s dokumentem WordprocessingML a obsahuje dva příklady refaktoringu pomocí čisté funkce.

Následující příklady kontrastuje se dvěma nečistými funkcemi a čistou funkcí.

Příklad: Implementace nečisté funkce, která změní člen statické třídy

V následujícím kódu HyphenatedConcat není funkce čistá funkce, protože upravuje aMember člen statické třídy:

public class Program
{
    private static string aMember = "StringOne";

    public static void HyphenatedConcat(string appendStr)
    {
        aMember += '-' + appendStr;
    }

    public static void Main()
    {
        HyphenatedConcat("StringTwo");
        Console.WriteLine(aMember);
    }
}
Module Module1
    Dim aMember As String = "StringOne"

    Public Sub HyphenatedConcat(ByVal appendStr As String)
        aMember = aMember & "-" & appendStr
    End Sub

    Sub Main()
        HyphenatedConcat("StringTwo")
        Console.WriteLine(aMember)
    End Sub
End Module

Tento příklad vytvoří následující výstup:

StringOne-StringTwo

Mějte na paměti, že je irelevantní, jestli mají změněná public data nebo private přístup, nebo je static členem, shared členem nebo členem instance. Čistá funkce nemění žádná data mimo funkci.

Příklad: Implementace nečisté funkce, která změní parametr

Kromě toho následující verze této stejné funkce není čistá, protože upravuje obsah jeho parametru, sb.

public class Program
{
    public static void HyphenatedConcat(StringBuilder sb, String appendStr)
    {
        sb.Append('-' + appendStr);
    }

    public static void Main()
    {
        StringBuilder sb1 = new StringBuilder("StringOne");
        HyphenatedConcat(sb1, "StringTwo");
        Console.WriteLine(sb1);
    }
}
Module Module1
    Public Sub HyphenatedConcat(ByVal sb As StringBuilder, ByVal appendStr As String)
        sb.Append("-" & appendStr)
    End Sub

    Sub Main()
        Dim sb1 As StringBuilder = New StringBuilder("StringOne")
        HyphenatedConcat(sb1, "StringTwo")
        Console.WriteLine(sb1)
    End Sub
End Module

Tato verze programu vytvoří stejný výstup jako první verze, protože HyphenatedConcat funkce změnila hodnotu (stav) prvního parametru Append vyvoláním členské funkce. Všimněte si, že k této změně dochází i přes skutečnost, že HyphenatedConcat používá předávání parametru call-by-value.

Důležité

Pokud pro odkazové typy předáte parametr podle hodnoty, bude výsledkem kopie odkazu na předaný objekt. Tato kopie je stále přidružená ke stejným datům instance jako původní odkaz (dokud není referenční proměnná přiřazena k novému objektu). Volání podle odkazu nemusí nutně vyžadovat, aby funkce upravila parametr.

Příklad: Implementace čisté funkce

Tato další verze programu ukazuje, jak funkci implementovat HyphenatedConcat jako čistou funkci.

class Program
{
    public static string HyphenatedConcat(string s, string appendStr)
    {
        return (s + '-' + appendStr);
    }

    public static void Main(string[] args)
    {
        string s1 = "StringOne";
        string s2 = HyphenatedConcat(s1, "StringTwo");
        Console.WriteLine(s2);
    }
}
Module Module1
    Public Function HyphenatedConcat(ByVal s As String, ByVal appendStr As String) As String
        Return (s & "-" & appendStr)
    End Function

    Sub Main()
        Dim s1 As String = "StringOne"
        Dim s2 As String = HyphenatedConcat(s1, "StringTwo")
        Console.WriteLine(s2)
    End Sub
End Module

Tato verze opět vytvoří stejný řádek výstupu: StringOne-StringTwo. Mějte na paměti, že pokud chcete zachovat zřetězenou hodnotu, je uložena v zprostředkující proměnné s2.

Jedním z přístupů, který může být velmi užitečný, je psát funkce, které jsou místně nečisté (tj. deklarují a upravují místní proměnné), ale jsou globálně čisté. Takové funkce mají mnoho z žádoucích vlastností kompozability, ale vyhněte se některým konvolutovaným funkčním programovacím idiomům, jako je třeba muset použít rekurzi, když jednoduchá smyčka dosáhne stejné věci.

Standardní operátory dotazů

Důležitou charakteristikou standardních operátorů dotazu je, že se implementují jako čisté funkce.

Další informace najdete v tématu Přehled operátorů standardních dotazů (C#) a Přehled operátorů standardních dotazů (Visual Basic).

Viz také