Lietuvių

Sužinokite, kaip šešiakampė architektūra, dar vadinama prievadų ir adapterių architektūra, gali pagerinti jūsų programų palaikomumą, testuojamumą ir lankstumą. Šis vadovas pateikia praktinių pavyzdžių ir naudingų įžvalgų programuotojams visame pasaulyje.

Šešiakampė architektūra: praktinis prievadų ir adapterių vadovas

Nuolat besikeičiančioje programinės įrangos kūrimo srityje, tvirtų, palaikomų ir testuojamų programų kūrimas yra svarbiausias dalykas. Šešiakampė architektūra, taip pat žinoma kaip prievadų ir adapterių architektūra, yra architektūrinis modelis, kuris sprendžia šias problemas atsiejant pagrindinę programos verslo logiką nuo jos išorinių priklausomybių. Šiuo vadovu siekiama suteikti išsamų supratimą apie šešiakampę architektūrą, jos privalumus ir praktines įgyvendinimo strategijas programuotojams visame pasaulyje.

Kas yra šešiakampė architektūra?

Šešiakampė architektūra, kurią sukūrė Alistair Cockburn, remiasi idėja izoliuoti programos branduolio verslo logiką nuo jos išorinio pasaulio. Ši izoliacija pasiekiama naudojant prievadus ir adapterius.

Įsivaizduokite tai taip: programos branduolys yra centre, apsuptas šešiakampio apvalkalo. Prievadai yra įėjimo ir išėjimo taškai šiame apvalkale, o adapteriai jungiasi prie šių prievadų, sujungdami branduolį su išoriniu pasauliu.

Pagrindiniai šešiakampės architektūros principai

Šešiakampės architektūros efektyvumą lemia keli pagrindiniai principai:

Šešiakampės architektūros naudojimo privalumai

Šešiakampės architektūros pritaikymas suteikia daug privalumų:

Šešiakampės architektūros įgyvendinimas: praktinis pavyzdys

Iliustruokime šešiakampės architektūros įgyvendinimą supaprastintu vartotojo registracijos sistemos pavyzdžiu. Aiškumui naudosime hipotetinę programavimo kalbą (panašią į Java ar C#).

1. Apibrėžkite branduolį (programą)

Programos branduolyje yra verslo logika, skirta naujo vartotojo registracijai.


// Core/UserService.java (arba UserService.cs)
public class UserService {
    private final UserRepository userRepository;
    private final PasswordHasher passwordHasher;
    private final UserValidator userValidator;

    public UserService(UserRepository userRepository, PasswordHasher passwordHasher, UserValidator userValidator) {
        this.userRepository = userRepository;
        this.passwordHasher = passwordHasher;
        this.userValidator = userValidator;
    }

    public Result<User, String> registerUser(String username, String password, String email) {
        // Patikrinti vartotojo įvestį
        ValidationResult validationResult = userValidator.validate(username, password, email);
        if (!validationResult.isValid()) {
            return Result.failure(validationResult.getErrorMessage());
        }

        // Patikrinti, ar vartotojas jau egzistuoja
        if (userRepository.findByUsername(username).isPresent()) {
            return Result.failure("Vartotojo vardas jau egzistuoja");
        }

        // Maišyti slaptažodį
        String hashedPassword = passwordHasher.hash(password);

        // Sukurti naują vartotoją
        User user = new User(username, hashedPassword, email);

        // Išsaugoti vartotoją saugykloje
        userRepository.save(user);

        return Result.success(user);
    }
}

2. Apibrėžkite prievadus

Apibrėžiame prievadus, kuriuos programos branduolys naudoja sąveikai su išoriniu pasauliu.


// Ports/UserRepository.java (arba UserRepository.cs)
public interface UserRepository {
    Optional<User> findByUsername(String username);
    void save(User user);
}

// Ports/PasswordHasher.java (arba PasswordHasher.cs)
public interface PasswordHasher {
    String hash(String password);
}

//Ports/UserValidator.java (arba UserValidator.cs)
public interface UserValidator{
  ValidationResult validate(String username, String password, String email);
}

//Ports/ValidationResult.java (arba ValidationResult.cs)
public interface ValidationResult{
  boolean isValid();
  String getErrorMessage();
}

3. Apibrėžkite adapterius

Įgyvendiname adapterius, kurie sujungia programos branduolį su konkrečiomis technologijomis.


// Adapters/DatabaseUserRepository.java (arba DatabaseUserRepository.cs)
public class DatabaseUserRepository implements UserRepository {
    private final DatabaseConnection databaseConnection;

    public DatabaseUserRepository(DatabaseConnection databaseConnection) {
        this.databaseConnection = databaseConnection;
    }

    @Override
    public Optional<User> findByUsername(String username) {
        // Įgyvendinimas naudojant JDBC, JPA ar kitą duomenų bazės prieigos technologiją
        // ...
        return Optional.empty(); // Vietos rezervavimo ženklas
    }

    @Override
    public void save(User user) {
        // Įgyvendinimas naudojant JDBC, JPA ar kitą duomenų bazės prieigos technologiją
        // ...
    }
}

// Adapters/BCryptPasswordHasher.java (arba BCryptPasswordHasher.cs)
public class BCryptPasswordHasher implements PasswordHasher {
    @Override
    public String hash(String password) {
        // Įgyvendinimas naudojant BCrypt biblioteką
        // ...
        return "hashedPassword"; //Vietos rezervavimo ženklas
    }
}

//Adapters/SimpleUserValidator.java (arba SimpleUserValidator.cs)
public class SimpleUserValidator implements UserValidator {
  @Override
  public ValidationResult validate(String username, String password, String email){
    //Paprasta patvirtinimo logika
     if (username == null || username.isEmpty()) {
            return new SimpleValidationResult(false, "Vartotojo vardas negali būti tuščias");
        }
        if (password == null || password.length() < 8) {
            return new SimpleValidationResult(false, "Slaptažodis turi būti bent 8 simbolių ilgio");
        }
        if (email == null || !email.contains("@")) {
            return new SimpleValidationResult(false, "Neteisingas el. pašto formatas");
        }

        return new SimpleValidationResult(true, null);
  }
}

//Adapters/SimpleValidationResult.java (arba SimpleValidationResult.cs)
public class SimpleValidationResult implements ValidationResult {
  private final boolean valid;
  private final String errorMessage;

    public SimpleValidationResult(boolean valid, String errorMessage) {
        this.valid = valid;
        this.errorMessage = errorMessage;
    }
  @Override
  public boolean isValid(){
    return valid;
  }

  @Override
  public String getErrorMessage(){
    return errorMessage;
  }
}



//Adapters/WebUserController.java (arba WebUserController.cs)
//Inicijuojantis adapteris - apdoroja užklausas iš žiniatinklio
public class WebUserController {
    private final UserService userService;

    public WebUserController(UserService userService) {
        this.userService = userService;
    }

    public String registerUser(String username, String password, String email) {
        Result<User, String> result = userService.registerUser(username, password, email);
        if (result.isSuccess()) {
            return "Registracija sėkminga!";
        } else {
            return "Registracija nepavyko: " + result.getFailure();
        }
    }
}


4. Kompozicija

Visko sujungimas. Atkreipkite dėmesį, kad ši kompozicija (priklausomybių įpurškimas) paprastai vyksta programos įėjimo taške arba priklausomybių įpurškimo konteineryje.


//Pagrindinė klasė arba priklausomybių įpurškimo konfigūracija
public class Main {
    public static void main(String[] args) {
        // Sukurti adapterių egzempliorius
        DatabaseConnection databaseConnection = new DatabaseConnection("jdbc:mydb://localhost:5432/users", "user", "password");
        DatabaseUserRepository userRepository = new DatabaseUserRepository(databaseConnection);
        BCryptPasswordHasher passwordHasher = new BCryptPasswordHasher();
        SimpleUserValidator userValidator = new SimpleUserValidator();

        // Sukurti programos branduolio egzempliorių, įpurškiant adapterius
        UserService userService = new UserService(userRepository, passwordHasher, userValidator);

        //Sukurti inicijuojantį adapterį ir prijungti jį prie paslaugos
        WebUserController userController = new WebUserController(userService);

        //Dabar galite tvarkyti vartotojo registracijos užklausas per userController
        String result = userController.registerUser("john.doe", "P@sswOrd123", "john.doe@example.com");
        System.out.println(result);
    }
}



//DatabaseConnection yra paprasta klasė tik demonstraciniais tikslais
class DatabaseConnection {
    private String url;
    private String username;
    private String password;

    public DatabaseConnection(String url, String username, String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }

    // ... metodai prisijungti prie duomenų bazės (neįgyvendinta dėl trumpumo)
}

//Result klasė (panaši į Either funkcinėje programavime)
class Result<T, E> {
    private final T success;
    private final E failure;
    private final boolean isSuccess;

    private Result(T success, E failure, boolean isSuccess) {
        this.success = success;
        this.failure = failure;
        this.isSuccess = isSuccess;
    }

    public static <T, E> Result<T, E> success(T value) {
        return new Result<>(value, null, true);
    }

    public static <T, E> Result<T, E> failure(E error) {
        return new Result<>(null, error, false);
    }

    public boolean isSuccess() {
        return isSuccess;
    }

    public T getSuccess() {
        if (!isSuccess) {
            throw new IllegalStateException("Rezultatas yra nesėkmė");
        }
        return success;
    }

    public E getFailure() {
        if (isSuccess) {
            throw new IllegalStateException("Rezultatas yra sėkmė");
        }
        return failure;
    }
}

class User {
    private String username;
    private String password;
    private String email;

    public User(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    // getter'iai ir setter'iai (praleista dėl trumpumo)

}

Paaiškinimas:

Pažangesni aspektai ir gerosios praktikos

Nors pagrindiniai šešiakampės architektūros principai yra paprasti, yra keletas pažangesnių aspektų, kuriuos reikia turėti omenyje:

Realaus pasaulio šešiakampės architektūros naudojimo pavyzdžiai

Daugelis sėkmingų įmonių ir projektų pritaikė šešiakampę architektūrą kurdami tvirtas ir palaikomas sistemas:

Iššūkiai ir kompromisai

Nors šešiakampė architektūra siūlo didelių privalumų, svarbu pripažinti susijusius iššūkius ir kompromisus:

Labai svarbu atidžiai įvertinti šešiakampės architektūros privalumus ir iššūkius atsižvelgiant į jūsų konkretaus projekto reikalavimus ir komandos galimybes. Tai nėra sidabrinė kulka, ir tai gali būti ne geriausias pasirinkimas kiekvienam projektui.

Išvada

Šešiakampė architektūra, pabrėžianti prievadus ir adapterius, suteikia galingą požiūrį į palaikomų, testuojamų ir lanksčių programų kūrimą. Atsiejant pagrindinę verslo logiką nuo išorinių priklausomybių, ji leidžia lengvai prisitaikyti prie besikeičiančių technologijų ir reikalavimų. Nors yra iššūkių ir kompromisų, kuriuos reikia apsvarstyti, šešiakampės architektūros privalumai dažnai nusveria išlaidas, ypač sudėtingoms ir ilgaamžėms programoms. Priimdami priklausomybių inversijos ir aiškių sąsajų principus, galite sukurti sistemas, kurios yra atsparesnės, lengviau suprantamos ir geriau pasirengusios atitikti šiuolaikinės programinės įrangos srities reikalavimus.

Šis vadovas pateikė išsamią šešiakampės architektūros apžvalgą, nuo jos pagrindinių principų iki praktinių įgyvendinimo strategijų. Mes skatiname jus toliau tyrinėti šias sąvokas ir eksperimentuoti taikant jas savo projektuose. Investicija į šešiakampės architektūros mokymąsi ir pritaikymą neabejotinai atsipirks ilgalaikėje perspektyvoje, lemdama aukštesnės kokybės programinę įrangą ir labiau patenkintas kūrėjų komandas.

Galiausiai, tinkamos architektūros pasirinkimas priklauso nuo konkrečių jūsų projekto poreikių. Priimdami sprendimą, atsižvelkite į sudėtingumo, ilgaamžiškumo ir palaikomumo reikalavimus. Šešiakampė architektūra suteikia tvirtą pagrindą kurti tvirtas ir pritaikomas programas, tačiau tai tik vienas įrankis programinės įrangos architekto įrankių dėžėje.