Jak ve WinForms zobrazovat výsledek z bussines vrstvy? Best practise   otázka

C#, WinForms

Dobrý den,

ve WinFormech bych chtěl po stisku tlačítka zavolat nějakou třídu a následně uživateli zobrazit hodnoty, která volaná třída vypočetla.

Tady je příklad pro ilustraci:

//udalost se pusti po klikntí na tlačitko

private void buttonResult_Click(object sender, EventArgs e)

{

int width = Int32.Parse(this.textBoxWidth.Text);

int height = Int32.Parse(this.textBoxHeight.Text);

SteelGain steelGain = new SteelGain(width, height);

this.textBoxResult.Text = steelGain.Weight.ToString();

}

Funguje to, ale prý je to špatně z hlediska návrhu aplikace. Poradíte mi nějaké lepší řešení? Vím, že blok můžu dát do separátní metody, ale to prý nestačí.

private void buttonResult_Click(object sender, EventArgs e)

{

ShowWeightOfGainSteel();

}

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nejde o to jak je to napsané v kódu ve smyslu v kolika metodách to je, ale jak je to rozdělené na vrstvy.. logiku by jste měl mít v nějaké jiné vrstvě, než je code behind té aplikace.. například v nějaké vrstvě service, v nějakém business modelu. Řešení je více, ale rozhodně není jejich popis na nějakou odpověď na fóru:

Zkuste hledat na googlu pod pojmy jako: seperation of concerns, WinForms MVVM, Winforms MVP, Winforms IOC,..

Například zde:

https://www.google.cz/?gfe_rd=cr&ei=7cgO...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za odpověďi.

třída SteelGain bude pouze provádět jednoduchý výpočet (width x height x konstanta) . Je možné ji nahradit statickou metodu.

int weight = SteelGain.GetWeigh(width, height);

Potřebuji jenom někde umísti kód, který načte vstupní data a postará se o zobrazeni výsledků.

Prokousával jsme se těmi návrhovými vzory, ale nikde tam nevidím model, protože zobrazuji výsledek pouze jedné statické funkce.

Co je v tomto případě nejvhodnější použít? S tím že cílem je vyhnout se code behinnd.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hezký večer,

code behind se nevyhnete a ani není důvod. Potíž je s třídou SteelGain, která by neměla být součástí projektu WebForms. Statickým metodám se, pokud možno, vyhněte. Pokud správně chápu, že třída SteelGain počítá váhu materiálu na plochu, v implementaci bych postupoval takto (předpokládejme, že výpočtů může být více, pro více materiálů):

V business vrstvě bych implementoval (v assembly s názvem např. Business) tyto třídy a rozhraní:

// strategy
    public interface IMaterialWeightCalculator
    {
        double Calculate(double width, double height);
    }

    // strategie (algoritmus) pro výpočet váhy oceli
    internal class SteelWeightCalculator : IMaterialWeightCalculator
    {
        const double constant = 1.3;

        public double Calculate(double width, double height)
        {
            return width * height * constant; // nějaký výpočet
        }
    }

    // strategie (algoritmus) pro výpočet váhy vody
    internal class WatterWeightCalculator : IMaterialWeightCalculator
    {
        const double constant = 0.6;

        public double Calculate(double width, double height)
        {
            return (width * height * constant) * Math.Log(width + height); // nějaký výpočet
        }
    }

Jedná se o návrhový vzor Strategy, čili pro každý výpočet (strategii/algorimus) samostatné třídy, které implementují společné rozhraní.

Pro tvoření instancí algoritmů jsem zvolil vzor Abstract factory, která mi, mimo jiné, zajišťuje, že se mi instance vytváří na jednom místě (taky v business vrstvě):

// abstract factory
    public interface IMaterialWeightCalculatorFactory
    {
        IMaterialWeightCalculator CreateCalculator(Material material);
    }

    // konkrétní factory vracejíc strategy
    public class MaterialWeightCalculatorFactory : IMaterialWeightCalculatorFactory
    {
        public IMaterialWeightCalculator CreateCalculator(Material material)
        {
            if (material == Material.Steel)
            {
                return new SteelWeightCalculator();
            }

            if (material == Material.Water)
            {
                return new WatterWeightCalculator();
            }

            throw new ArgumentException("Invalid material type.");
        }
    }

    // typy materiálů
    public enum Material
    {
        Steel,
        Water
    }

Použití v prezentační logice (code behind) potom následující:

        private IMaterialWeightCalculatorFactory _materialWeightCalculatorFactory;

        private IMaterialWeightCalculatorFactory MaterialWeightCalculatorFactory 
        {
            get 
            {
                return _materialWeightCalculatorFactory = _materialWeightCalculatorFactory ?? new MaterialWeightCalculatorFactory();
            }
        }
        
        // pro ocel
        public void buttonSteel_Click(object sender, EventArgs e)
        {
            var width = double.Parse(TextBox2.Text); // převzetí vstupu
            var height = double.Parse(TextBox3.Text); // převzetí vstupu

            var svc = MaterialWeightCalculatorFactory.CreateCalculator(Material.Steel);

            TextBox1.Text = svc.Calculate(width, height);
        }

        public void buttonWater_Click(object sender, EventArgs e)
        {
            var width = double.Parse(TextBox4.Text); // převzetí vstupu
            var height = double.Parse(TextBox5.Text); // převzetí vstupu

            var svc = MaterialWeightCalculatorFactory.CreateCalculator(Material.Water);

            TextBox6.Text = svc.Calculate(width, height);
        }

Po té stavět něco nad tím, dle potřeby. Nevím, možná je to pro Váš charakter aplikace kanón na vrabce, ale člověk nikdy neví, jak se aplikace bude dál rozšiřovat, lze to jen predikovat z předchozích zkušeností.

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hezký večer,

z tak krátkého kusu kódu je dosti těžké vyvozovat nějaké závěry, ale dle mého:

První dva řádky OK - zpracování vstupů

Třída "SteelGain" by měla být v samostatné assembly z názvem např. Business, Application, BL, AL apod. A neměla by obsahovat data + logiku (proměnné width, height a property Weight). Ale jednu metodu GetWeight(width, height) vracejíc weight nebo nějaký komplexní typ. Ideálně neinicializovaná přes "new" ale přes IoC kontejner.

Obecně by business vrstva měla být samostatná a obsahovat jen logiku aplikace (výpočty, zpracování dat ...), tzn. assembly, ze které udělám dll(ku) a tu můžu použít v jakékoliv .NET prezentační technologii (web, windows forms, WPF atd...).

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pokud správně chápu Váš příspěvek, tak z něj plyne, že jedinou správnou cestou je IoC, nicméně nemyslím si, že dependency ijenction je jedinou možnou cestou.

Návrhových vzorů je mnoho (Singleton, Adapter, Servant, Proxy....) a je na citu vývojáře, který pro danou situaci použije, respektive, který v danou nejlépe splňuje potřeby aplikace.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hezký večer,

určitě netvrdím, že to je jediná (a nejlepší) možnost. Jen říkám: "já bych to udělal takto".

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback