DEV Community

nikosst
nikosst

Posted on

Helper Classes vs Extension Methods

Ποια είναι η διαφορά και πότε χρησιμοποιείς το καθένα

Στην καθημερινή ανάπτυξη λογισμικού, πολύ συχνά θα βρεθείς να γράφεις “βοηθητικό” κώδικα. Δηλαδή μικρές λειτουργίες που δεν ανήκουν ξεκάθαρα σε ένα domain object, αλλά χρειάζονται ξανά και ξανά.

Εδώ εμφανίζονται δύο βασικά patterns:

  • Helper Classes
  • Extension Methods

Πολλοί τα μπερδεύουν ή τα χρησιμοποιούν τυχαία. Όμως η διαφορά τους δεν είναι τεχνική λεπτομέρεια, είναι θέμα καθαρότητας, αναγνωσιμότητας και επικοινωνίας μέσω κώδικα.

Και αυτό είναι το πιο σημαντικό.


Helper Classes

Τι είναι

Μια helper class είναι απλά μια static class που περιέχει βοηθητικές μεθόδους.

Δεν “ανήκει” σε κάποιο object. Είναι ένα εξωτερικό εργαλείο.


Παράδειγμα 1: String Helper

public static class StringHelper
{
    public static bool IsNullOrShort(string text)
    {
        return string.IsNullOrEmpty(text) || text.Length < 5;
    }
}

Enter fullscreen mode Exit fullscreen mode

Χρήση:

string name = "Nikos";

if (StringHelper.IsNullOrShort(name))
{
    Console.WriteLine("Invalid name");
}

Enter fullscreen mode Exit fullscreen mode

Τι συμβαίνει εδώ

  • Έχω ένα string
  • Θέλω να κάνω κάτι με αυτό
  • Πάω σε μια άλλη class για να το κάνω

Δηλαδή: φεύγεις από το object


Παράδειγμα 2: Date Helper

public static class DateHelper
{
    public static bool IsWeekend(DateTime date)
    {
        return date.DayOfWeek == DayOfWeek.Saturday ||
               date.DayOfWeek == DayOfWeek.Sunday;
    }
}

Enter fullscreen mode Exit fullscreen mode

Χρήση:

if (DateHelper.IsWeekend(DateTime.Now))
{
    Console.WriteLine("Relax!");
}

Enter fullscreen mode Exit fullscreen mode

Πλεονεκτήματα

  • Απλό και ξεκάθαρο
  • Μαζεύεις utilities σε ένα μέρος
  • Δεν “πειράζεις” υπάρχουσες classes

Μειονεκτήματα

  • Δεν είναι intuitive
  • Δεν διαβάζεται φυσικά
  • Μεγαλώνει εύκολα και γίνεται “dumping ground”

Extension Methods

Τι είναι

Extension methods σου επιτρέπουν να “προσθέσεις” μεθόδους σε υπάρχουσες classes χωρίς να τις αλλάξεις.


Παράδειγμα 1: String Extension

public static class StringExtensions
{
    public static bool IsNullOrShort(this string text)
    {
        return string.IsNullOrEmpty(text) || text.Length < 5;
    }
}

Enter fullscreen mode Exit fullscreen mode

Χρήση:

string name = "Nikos";

if (name.IsNullOrShort())
{
    Console.WriteLine("Invalid name");
}

Enter fullscreen mode Exit fullscreen mode

Τι αλλάζει εδώ;

Αντί να λες:

“πάω στο helper”

λες:

“το ίδιο το string ξέρει να το κάνει”


Παράδειγμα 2: Date Extension

public static class DateExtensions
{
    public static bool IsWeekend(this DateTime date)
    {
        return date.DayOfWeek == DayOfWeek.Saturday ||
               date.DayOfWeek == DayOfWeek.Sunday;
    }
}

Enter fullscreen mode Exit fullscreen mode

Χρήση:

if (DateTime.Now.IsWeekend())
{
    Console.WriteLine("Relax!");
}

Enter fullscreen mode Exit fullscreen mode

Πώς το “βρίσκει” ο compiler

Εδώ βρίσκεται όλη η “μαγεία”, που στην πραγματικότητα δεν είναι μαγεία αλλά ένας πολύ συγκεκριμένος μηχανισμός του compiler.

Όταν γράφεις name.IsNullOrShort(), ο compiler ΔΕΝ ψάχνει μόνο μέσα στο string για τη μέθοδο. Αν δεν τη βρει εκεί, κάνει ένα δεύτερο βήμα: κοιτάει όλα τα extension methods που είναι διαθέσιμα μέσω των using statements στο αρχείο σου.

Δηλαδή, σκανάρει τα static classes στα namespaces που έχεις κάνει import και ψάχνει για μεθόδους που έχουν this string ως πρώτο parameter.

Μόλις βρει μια που ταιριάζει, τη “μεταφράζει” εσωτερικά σε κανονική static κλήση, π.χ. StringExtensions.IsNullOrShort(name).

Αν δεν υπάρχει το σωστό using, η μέθοδος απλά δεν υπάρχει για τον compiler γι’ αυτό και πολλές φορές “ξαφνικά” δουλεύει μόλις προσθέσεις ένα namespace.

Με λίγα λόγια, ο compiler δεν αλλάζει το string· απλά σου δίνει έναν πιο φυσικό τρόπο να καλέσεις μια κανονική static μέθοδο.


Παράδειγμα: Πώς ο compiler βρίσκει (ή δεν βρίσκει) το extension

Ορίζεις το extension

namespace MyProject.Extensions
{
    public static class StringExtensions
    {
        public static bool IsNullOrShort(this string text)
        {
            return string.IsNullOrEmpty(text) || text.Length < 5;
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Περίπτωση Α: ΧΩΡΙΣ using

string name = "Nikos";

bool result = name.IsNullOrShort(); //Compile error

Enter fullscreen mode Exit fullscreen mode

Error:
string does not contain a definition for 'IsNullOrShort'

Γιατί;
Ο compiler δεν βλέπει το extension, γιατί δεν έχεις κάνει import το namespace.

Περίπτωση Β: ΜΕ using

using MyProject.Extensions;

string name = "Nikos";

bool result = name.IsNullOrShort(); // Works

Enter fullscreen mode Exit fullscreen mode

Τι έγινε εδώ;

  • Ο compiler δεν βρίσκει τη μέθοδο στο string
  • Κοιτάει στα extensions του namespace
  • Βρίσκει:
public static bool IsNullOrShort(this string text)

Enter fullscreen mode Exit fullscreen mode

Και το μετατρέπει σε:

StringExtensions.IsNullOrShort(name);

Απόδειξη ότι είναι το ίδιο

using MyProject.Extensions;

string name = "Nikos";

bool a = name.IsNullOrShort();
bool b = StringExtensions.IsNullOrShort(name);

Enter fullscreen mode Exit fullscreen mode

Τα a και b είναι ακριβώς το ίδιο πράγμα

Το extension method:

  • δεν ανήκει πραγματικά στο string
  • δεν αλλάζει την class
  • απλά γίνεται “ορατό” μέσω using
  • και ο compiler το μετατρέπει σε static call

Η Πραγματική Διαφορά

Δεν είναι θέμα “τι κάνει”, αλλά πώς διαβάζεται.

Σύγκριση

Helper:

if (StringHelper.IsNullOrShort(name))
Enter fullscreen mode Exit fullscreen mode

Extension:

if (name.IsNullOrShort())
Enter fullscreen mode Exit fullscreen mode

Πότε χρησιμοποιείς τι

Χρησιμοποίησε Extension Methods όταν:

  • Η λειτουργία σχετίζεται ξεκάθαρα με το object
  • Θες readable / fluent code
  • Θες να γράφεις “σαν πρόταση”

Παραδείγματα:

  • string.IsValidEmail()
  • date.IsWeekend()
  • list.IsEmpty()

Χρησιμοποίησε Helper Class όταν:

  • Η λειτουργία είναι γενική
  • Δεν ανήκει σε ένα object
  • Έχεις logic που χρησιμοποιεί πολλά types

Παράδειγμα:

public static class MathHelper
{
    public static int Add(int a, int b)
    {
        return a + b;
    }
}

Enter fullscreen mode Exit fullscreen mode

Δεν έχει νόημα:

a.Add(b) 
Enter fullscreen mode Exit fullscreen mode

Να θυμάσαι..

Η διαφορά δεν είναι τεχνική, είναι νοητική.

Helper Class
εργαλείο έξω από το object

Extension Method
συμπεριφορά πάνω στο object


nikosstit@gmail.com

Top comments (0)