Refaktoryzacja przez odchudzanie Modelu LINQtoSQL na ModelTiny w widoku

0

Napisałem program w C# w WindowsForms korzystający z MS SQL Server, jako ORM wykorzystałem LINQtoSQL, wykorzystuje architekturę MVPresenter: Model(automat z LINQtoSQL), DAL(repozytoria), Logika(Prezentery i klasy pomocnicze) i Widok(WindowsForms).

Oprogramowałem mały wycinek odpowiedzialny za zarządzanie pracownikiem, działem firmy, stanowiskiem pracy (dodawanie, edycja, usuwanie, wykaz wszystkich itp.). Ten wycinek działa, ale pare rzeczy robiłem na skróty, teraz chce to poprawić, tak zeby to faktycznie miało ręce i nogi i żebym wypracowaną architekturę na tym wycinku mógł powielać w dalszej pracy nad programem. Ale nie chce działać po omacku, bo za dużego doświadczenia nie mam i wiele rzeczy które tu wykorzystuje robie po raz pierwszy, także na samym końcu postu mam pare pytań:

W całym programie korzystam z modelu wygenerowanego automatycznie przez LINQtoSQL. W widoku również (żeby szybciej zobaczyć efekty). Mam wrażenie ze szczególnie w oknach dodawania i edycji to obciąża i zwalnia program bo np. w oknie edycji pracownika do ComboBoxów (zmiana właściwości z kluczy obcych) binduje listy z pełnymi obiektami np. DziałFirmy, StanowiskoPracy, Przełożony itp. a w ComboBoxach później używam tylko dwóch właściwosci w ten sposób:

        private void ZaladujDoComboListeDzialow()
        {
            cBox_Dzial.DataSource = presenter.ZwrocWszystkieDzialy();   //zwraca List<DzialFirmy>   gdzie klasa DzialFirmy jest pokazana poniżej
            cBox_Dzial.ValueMember = "id";
            cBox_Dzial.DisplayMember = "NazwaDzialu";      
        }
 

Klasa automatyczna wyglada jak poniżej, znaczną cześć jej wyciąłem, dałem tylko prawie wszystkie pola prywatne, konstruktora i jedną właściwosc, zeby nie zaciemniac bardzij obrazu:

	public partial class DzialFirmy : INotifyPropertyChanging, INotifyPropertyChanged
	{
		
		private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);		
		private int _id;		
		private string _NazwaDzialu;		
		private string _LokalizacjaDzialu;	
	        //(...)
		private EntitySet<Pracownik> _Pracowniks;
		
    #region Extensibility Method Definitions
    partial void OnLoaded();
    partial void OnValidate(System.Data.Linq.ChangeAction action);
    partial void OnCreated();
    partial void OnidChanging(int value);
    partial void OnidChanged();
    partial void OnNazwaDzialuChanging(string value);
    partial void OnNazwaDzialuChanged();
    partial void OnLokalizacjaDzialuChanging(string value);
    partial void OnLokalizacjaDzialuChanged();
    #endregion
		
		public DzialFirmy()
		{
			this._Pracowniks = new EntitySet<Pracownik>(new Action<Pracownik>(this.attach_Pracowniks), new Action<Pracownik>(this.detach_Pracowniks));
			OnCreated();
		}
		
		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
		public int id
		{
			get
			{
				return this._id;
			}
			set
			{
				if ((this._id != value))
				{
					this.OnidChanging(value);
					this.SendPropertyChanging();
					this._id = value;
					this.SendPropertyChanged("id");
					this.OnidChanged();
				}
			}
		}
	//(...)
	} 

Chce wprowadzić nowe klasy typu Tiny, do użytku tylko w widoku np do podpinania ich do kontrolek form i operowaniu na ich ID które jest to samo co w odpowiadającej im klasie z LINQtoSQL np:

    public class DzialFirmyTiny
    {
        public int Id { get; set; }
        public string Nazwa { get; set; }
    }

Tworzyc te obiekty Tiny mam zamiar w repozytorium jak poniżej i pozniej przekazywać do DataSource Comboboxów w Widoku:

        public List<DzialFirmyTiny> PobierzWszystkieDzialyJakoTiny()
        {
            var query = from d in db.Dzialy()
                        select new DzialFirmyTiny { Id = d.id, Nazwa = d.NazwaDzialu };

            return query.AsQueryable().ToList();
        }
 

i teraz pytania:
1) Czy takie odchudzanie klas zwiększy szybkość działania programu?
2) Czy taka odchudzona klasa to właśnie lepiej żeby była klasą czy strukturą?
3) Przed wprowadzeniem typów TINY mój widok(Formy) miał referencje do modelu z którego korzystały kontrolki na formie. Czy typy tiny powinny być również w przestrzeni Modelu czy trzymać ich definicje w widoku? W drugim przypadku repozytoria w DAL beda musiały mieć referencje na widok.
4) Czy typami Tiny lepiej zastąpić korzystanie z widoków bazodanowych. Widoki utworzyłem np. dla Pracowanika żeby łatwiej zbindować List<PracownikView> do DataGridView i zeby informacje w datagridzie były czytelnymi dla uzytkownika bez ciągów cyferek kluczy obcych. Ale wtedy takie tworzenie odpowiedniego Tiny przerzucałbym na LINQ w repozytorium. Co byłoby wydajniejsze?

0

Czy takie odchudzanie klas zwiększy szybkość działania programu

A czy szybkość działania programu była problemem?
Bo jeśli nie, to po prostu nie warto kombinować...

0

Na razie nie jest problemem, ale na razie zrobiłem mały wycinek tego co chce w całości zrobić. Nawet nie wiem czy to jest 1% tego co zamierzam i wtedy to już może być problem.

1
  1. W przypadku aplikacji desktopowej nie, a może nawet będzie przeciwnie. To ma większe znaczenie w przypadku aplikacji webowych, gdy te dane musisz przesłać przez sieć do przeglądarki. No, ale wygenerowane automatycznie klasy są dość ciężkie, np. zmiana wartości właściwości powoduje niepotrzebne rzucanie zdarzeń, itp., więc utworzenie klas o których piszesz ma sens.
  2. A będziesz miał jakiś zysk z przekazywania jej przez wartość? Jeśli nie, to oczywiście, że klasą.

W drugim przypadku repozytoria w DAL beda musiały mieć referencje na widok.

I osiągniesz cykliczną zależność. :) Oczywiście, że repozytoria nie mogą mieć referencji do widoku.
Twoje nowe klasy powinny być dostępne dla Prezenterów, bo to Prezentery maja konwertować z Encji (wygenerowanych przez LINQ to SQL) na te Twoje klasy.
4) Widoki bazodanowe są wydajniejsze niż kod SQL nieudolnie tworzony przez porzuconego już ORMa. Zwłaszcza, jeśli są to skomplikowane joiny i projekcje. Ale przecież na podstawie widoku bazodanowego możesz wygenerować klasę, i ją pokazywać w widoku.

Tak w ogóle, to te Twoje klasy "Tiny" na całym świecie nazywa się viewmodelami.

0

Ad.4

Tak też robię, widok z bazy danych dodałem do DataContext przez kreatora i on mi to zmapował na klase i to lekką klasę bez rzucania zdarzeń przy ustawianiu właściwości. I teraz tak jeżeli nie zrobie do tego identycznej klasy "viewmodel" to bede musial utrzymac referencje w widoku na model. A jezeli zrobie do tego klase "viewmodel" to bedzie ona identyczna z klasa w modelu, ale za to zniknie referencja do modelu w widoku - czyli chyba warto dodac nowy typ tylko w innej przestrzeni nazw?

1

Ja bym dodał, bo dodanie kolejnej klasy to mały wysiłek, a zyskujemy na tym ładną architekturę i wyraźne SoC.

1 użytkowników online, w tym zalogowanych: 0, gości: 1