Ściągnij VS 2010 i .NET Framework 4.0 CTP

Tipsy   |    28 październik 2008 1:08


Właśnie zauważyłem że Nick spostrzegł że można ze stron Microsoftu ściągnąć CTP VS 2010 i .NET Framework 4.0. Już nie mogę doczekać się kiedy się ściągnie i zaraz będę pisał co tam nowego.


Nowy dział: Szybkie kontrolki i komponenty

Polishwords   |    19 październik 2008 6:23


Szybkie kontrolki i komponentyW kategorii programowanie w Visual Studio dodałem nowy dział Szybkie kontrolki i komponenty. W tym dziale będą pojawiać się co tydzień filmy na temat kontrolek i komponentów dostępnych w .NET Framework. Już jest jeden i zawiera informacje o 3 podstawowych komponentach do wyświetlania okien dialogowych: ColorDialog, FolderBrowserDialog, FontDialog i OpenFileDialog. Pozwalają one odpowiednio na: wybór koloru, wybór foldera,  wybór czcionki i wybór pliku do otwarcia.

W sumie ta nowa seria tutoriali mogła trafić do innych działów, ale stwierdziłem, że od .NET 3.5 jest tak dużo różnych klas, komponentów i kontrolek, że początkujący użytkownicy mogą się w tym wszystkim pogubić tak jak każdy gubił się w pakietach Borlanda. A warto o tym wspomnieć bo “Intellisense” Borlanda było całkiem dobre. Problemem było jednak to, że lista np. tysiąca metod danej klasy wcale nie pomaga w programowaniu. Akurat dla programistów działających od wersji .NET Framework 1.1 to nie jest problem, bo dojrzewali razem z tym środowiskiem i wiedzą, jakie kontrolki do czego służą i nie mają problemu ich odnaleźć.

Tak więc powstał nowy dział. Dział ten charakteryzuje się tym, że będą tam szybkie przypadki użycia komponentów i kontrolek. Tj. jeżeli pod lupę bierzemy komponent FontDialog, to pokazuję jak wyświetlić okno dialogowe wyboru czcionki i używam wyniku tego okna do zmiany czcionki etykiety tekstowej. I tak po kolei każdy komponent będzie przedstawiany w tej części: szybko i praktycznie. Cała seria zamknie się kiedy przedstawione zostaną wszystkie podstawowe komponenty i kontrolki dostępne w .NET Framework 3.5.

Za tydzień (prawdopodobnie w niedzielę / poniedziałek) planuję dodać drugi odcinek serii czyli komponenty odpowiedzialne za drukowanie. Pozdrawiam i życzę miłego oglądania!


Kiedy nie warto używać DataSet Designera

Tipsy   |    2 wrzesień 2008 1:55


Każdy kto oglądał chociaż jedną prezentację na temat Visual Studio, wie jak efektowny jest DataSet Designer dołączony do tego narzędzia. Pozwala on na szybkie zmapowanie struktur bazy do struktur w kodzie przez co otrzymujemy silnie typowanego DataSeta. Dzięki temu można odwoływać się do elementów DataSeta “po kropce”, czyli np. DataSet.Tabela1.Wiersze[5].KolumnaA.

Jest to dosyć wygodne narzędzie i na początku wydaje się, że dzięki niemu będzie można podbić świat i okoliczne galaktyki. Jednak rzeczywistość wygląda tak, że to narzędzie może służyć do podbicia podwórka ew. osiedla albo miasta, ale już kraju to się tym nie podbije.

Kreator DataSeta jest przydatny jeżeli masz do napisania prostą aplikację. Powiedzmy 3-4 tabele i mało relacji, mało obliczeń. Przydatny jest także do programów dla nauki. Wtedy możesz szybko przygotować widoki na dane, ekrany edycyjne, szybko zrobić obliczenia statystyczne. Jednak jeżeli piszesz komercyjny program, który ma działać dobrze i chcesz zapewnić sobie spokój w nocy, po prostu zrezygnuj z kreatora DataSeta.

Oczywiście ten post nie ma na celu zniechęcać całkowicie do kreatora, ale dać szerszy obraz tego, jakie przygody czekają na podróżnika, który odwiedzi świat kreatora DataSeta.

Problemy przedstawione w tym poście dotyczą zarówno wersji Visual Studio 2005 jak i VS 2008, w której to nie zmieniło się dużo jeżeli chodzi o architekturę kodu generowanego przez kreator. A zaczniemy od niego. Cała zabawa w pisanie dobrego kreatora polega na tym, żeby kod przez niego wygenerowany był łatwo debuggowalny jeżeli coś pójdzie nie tak. W końcu błędów w zaprojektowaniu kreatora nie da się uniknąć. Chcemy mieć pewność, że jeżeli kreator zadziała nie tak, będziemy mogli ręcznie naprawić jego błędy.

Skąd błędy w kreatorze DataSeta

Tak jest w przypadku kreatora okien (designera okien), ale nie w przypadku kreatora DataSeta.  Kod generowany jest w sposób chaotyczny, a elementy, które powinny być ze sobą jasno powiązane, nie są. Spójrz na ten kawałek wygenerowanego kodu:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
private void InitCommandCollection() {
this._commandCollection = new global::System.Data.SqlClient.SqlCommand[2];
this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand();
this._commandCollection[0].Connection = this.Connection;
this._commandCollection[0].CommandText = “SELECT ID, NAME from tabTabela”;
this._commandCollection[0].CommandType = global::System.Data.CommandType.Text;
this._commandCollection[1] = new global::System.Data.SqlClient.SqlCommand();
this._commandCollection[1].Connection = this.Connection;
this._commandCollection[1].CommandText = “SELECT ID, TELEFON from tabUser”;
this._commandCollection[1].CommandType = global::System.Data.CommandType.Text;
}

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")]
[global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Fill, true)]
public virtual int Fill(MyDataSet.MyDataTable dataTable) {
this.Adapter.SelectCommand = this.CommandCollection[0];
if ((this.ClearBeforeFill == true)) {
dataTable.Clear();
}
int returnValue = this.Adapter.Fill(dataTable);
return returnValue;
}
Co z tego przydługiego kodu wynika? Otóż to, że w kodzie wygenerowanym przez kreatora SqlCommand nie jest powiązane z metodami. Po prostu ktoś kto pisał tego kreatora, przyjął, że zapytania do bazy danych będą trzymane w  kolekcji _commandCollection, a w momencie wywołania konkretnej metody, odpowiednie zapytanie zostanie wstawione do SqlDataAdapter tego kreatora (czyli this.Adapter). W ten sposób nie można określić z jakiego zapytania korzysta na przykład metoda Fill, albo inna, własna, którą możesz przecież dodać z poziomu kreatora. Czyli reasumując: widzisz zapytanie w kreatorze, ale z poziomu kodu nie wiesz jakie zapytanie (PobierzUnikalneImiona, PobierzSumeVat itp.) korzysta z jakiego zapytania (’Select distinct First_Name’, “Select SUM(VAT)’).

Zazwyczaj wiedza ta nie jest potrzebna. Jednak sposób zaprojektowania tego rozwiązania jest przykładem wielu miejsc w kodzie generowanym przez kreatora gdzie trzeba wróżyć z fusów. Jest to o tyle ważne, że obsługa tego kodu działa w dwie strony: na podstawie tego co ustawiasz w kreatorze jest tworzony kod DataSeta, a z kodu DataSeta jest tworzone to co widzisz w kreatorze. A w tym miejscu twórca kreatora musi domyślać się jakie zapytanie jest powiązane z jaką metodą. Domyślanie się takich rzeczy jest niebezpieczne, bo może prowadzić do błędów i tak się właśnie dzieje czasem w kreatorze. Takie miejsca powodują, że czasem typowany DataSet po prostu się psuje. Dlatego proste poprawianie bugów w kodzie DataSeta tutaj nie wystarczy, trzeba by było zmienić sposób w jaki kreator serializuje ustawienia do kodu. Wtedy szanse na błędy podczas tego zamkniętego cyklu kod-kreator byłyby mniejsze.

Problem jest taki, że każdy taki błąd zniechęca użytkowników do używania kreatora i tak jest też w tym przypadku. Coś podobnego można było zaobserwować gdy rozwijał się rynek programów WYSIWYG do tworzenia stron internetowych. Po latach uciążliwości z FrontPage, który generował wielkie, nieoptymalne, nieczytelne i często wadliwe pliki HTML (wtedy jescze), pojawił się konkurencyjny program Dreamweaver, który generował piękny kod HTML. W miejscu gdzie była spacja była spacja a nie dziesiątki niepotrzebnych znaczników z których każdy zwiększał ryzyko tego, że strona nie będzie chodzić poprawnie nigdzie poza FrontPage. Dreamweaver pokazał, że można generować i interpretować przejrzysty kod i że to jest droga do osiągnięcia sukcesu z kreatorami. Szkoda, że w tym przypadku team Visual Studio nie uczy się z innych obszarów działalności swojej firmy.

O tym problemie pisałem już przeszło 2 miesiące temu na Connect i bez odzewu. Możliwe, że już wystarczająco dużo osób zniechęciło się do tego designera, żeby team VS planował go dalej rozwijać.

Jak zapobiec błędom

Tutaj pojawia się problem. Ponieważ jeżeli kreator DataSeta popełni błąd tak że nie będzie się uruchamiał znowu to jedyne co zostaje to otworzyć ręcznie kod i znaleźć błąd i go usunąć. Niestety w tym momencie twórcy DataSeta typowanego nie dają żadnej pomocy. Zakładają przy tym pewnie, że wygenerowany kod będzie działający w 100%. Niestety tak nie jest i czasem dzieje się tak, że za którymś razem kreator po prostu już się nie otworzy. Na przykład przez taki błąd:

Column requires a valid DataType.

Oprócz informacji o tym, że któraś kolumna nie ma poprawnego typu nic więcej się nie dowiemy. Podpięcie drugiego Visuala tutaj nic nie da. Tak samo Stack Trace, który wcale nie zaskakująco wygląda tak:

at System.Data.DataColumn.set_DataType(Type value)
at System.Data.XSDSchema.SetProperties(Object instance, XmlAttribute[] attrs)
at System.Data.XSDSchema.HandleElementColumn(XmlSchemaElement elem, DataTable table, Boolean isBase)
at System.Data.XSDSchema.HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, Boolean isBase)
at System.Data.XSDSchema.HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, Boolean isNillable)
at System.Data.XSDSchema.InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, Boolean isRef)

(dalsza część pominięta dla przejrzystości postu)

Nie pozostaje w tym momencie nic jak szukanie na oślep w kodzie wygenerowanym przez kreator. A wystarczyłoby dodać odpowiednią informację jakiej kolumny dotyczy błąd. Wtedy znalezienie problemu na własną rękę byłoby możliwe. No bo nie oszukujmy się, że przy zastosowanej architekturze kodu ręczne naprawy są nieuniknione.

Podsumowanie

Podsumowując staraj się używać kreatora DataSeta z głową i nie zawsze. Jest to wygodne narzędzie - owszem. Ale tylko do pewnego momentu. Zwłaszcza nie polecam korzystania z DataSeta bez robienia kopii zapasowych albo posiadania kontroli wersji. A jaka będzie przyszłość tego narzędzia? Czy będzie poprawiane? Nie sądzę i raczej myślę, że w końcu zostanie wprowadzony zamiennik, który będzie to wszystko realizwał zupełnie inaczej, bo na podstawie tego co jest nie da się dużo naprawić w zachowaniach kreatora DataSeta. Pozostaje mieć nadzieję, że team VS uczy się na błędach i nie popełni tych samych w przypadku kolejnych kreatorów, które są nieuniknione w środowiskach RAD.


Microsoft naprawił buga!

Tipsy   |    3 czerwiec 2008 10:06


W trakcie używania DataSet designera natrafiłem na pewnego buga, który istniał od wersji 2005 Visual Studio. Wygląda on w ten sposób, że dodając do tabeli kolumnę z ustawionym Expression nie można rekonfigurować ponownie DataSeta.

Przeczytaj całość >>


Problem z przeciążaniem Text

Tipsy   |    26 listopad 2007 10:30


Powiedzmy, że chcę mieć nową kontrolkę. Dziedziczę z np. klasy Panel i piszę

[Kod C#]
[Browsable(true)]
/// <summary>
/// Text to display
/// </summary>
public new string Text
{
get { return _text; }
set { if (_text != value) { _text = value; Invalidate(); } }
}

wrzucam z Toolbara tą nową kontrolkę z właściwością Text. Można teraz edytować pole Text we właściwościach kontrolki w czasie projektowania.
Ale właściwość Text nie jest serializowana do InitializeComponents.

Jak się okazało, ludzie radzą, aby dodać jeszcze jeden atrybut:

[Kod C#]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
/// <summary>
/// Text to display
/// </summary>
public new string Text
{
get { return _text; }
set { if (_text != value) { _text = value; Invalidate(); } }
}

Atrybut DesignerSerializationVisibility określa jak ma być serializowana właściwość. Wydawałoby się, że teraz właściwość powinna działać dobrze.
Ale niestety tak nie jest. Zachowanie jest nadal to samo: można ustawić właściwość, ale nie jest ona zapisywana do InitializeComponents czyli za pierwszym
razem kiedy Visual Studio będzie serializowało właściwości klasy, właściwość Text zostanie porzucona.

Kilka wątków na ten temat na różnych forach albo kończy się rozwiązaniem powyższym, które wygląda na to, że czasem wystarczy (możliwe, że
został dodany inny atrybut, który powoduje poprawne zachowanie tej właściwości). Moje próby znalezenia takiej właściwości zakończyły się
niestety niepowodzeniem.

Porzuciłem już nadzieję na to, żeby zachować normalne nazewnictwo tej właściwości, dodałem jeszcze tylko z ciekawości jeden atrybut:

[Kod C#]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[DefaultValue("")]
/// <summary>
/// Text to display
/// </summary>
public new string Text
{
get { return _text; }
set { if (_text != value) { _text = value; Invalidate(); } }
}

No i okazało się, że dodanie atrybutu DefaultValue powoduje, że serializacja działa już normalnie.
Może ktoś jest w stanie wyjaśnić, dlaczego po dodaniu DefaultValue serializacja  w tym bardzo szczególnym wypadku działa dobrze?


Zmiany w Windows Forms - podsumowanie

Polishwords   |    9 listopad 2007 10:29


Wszystkie ze zmian, które zapowiedziałem poprzednio zostały wprowadzone. Oprócz tego powiększyłem czcionkę, żeby pytania były bardziej czytelne, a struktura bardziej przejrzysta.

Na razie są tylko odpowiedzi na najczęstsze pytania z Windows Forms, ale możliwe, że niedługo pojawi się podobny dział dla ASP i może  .NET 3.5 i Visual Studio 2008?

Póki co jednak szukam dalej osób chętnych do tłumaczenia wpisów. Zajęcie nie jest trudne. Wystarczy znajomość języka angielskiego i .NET-a (podstawowa). Dzięki tłumaczeniu tych wpisów można się nauczyć naprawdę dużo - są to w większości tricki, których trudno szukać w książkach na temat .NET-a, a które trzeba stosować w codziennej pracy z tym środowiskiem uruchomieniowym. Na zajęcie to można poświęcić np. 15 minut dziennie i to w zupełności wystarczy, żeby przetłumaczyć parę pytań. Niby to mało w porównaniu do całkowitej liczby, ale są to naprawdę wartościowe informacje.

Planuję w najbliższym czasie zrobić oddzielne miejsce na stronie, gdzie będzie wyszczególniona lista osób uczestniczących w rozwoju FAQ.

Także serdecznie zachęcam do udziału w projekcie.


Ciekawe porównania

Przemyślenia   |    1 lipiec 2007 11:46


Przeglądając ostatnio Internet, pełen podziwu dla pierwszych na świecie rozwiązań w Visual Studio i .NET Frameworku postanowiłem poszukać kogoś, z kim mógłbym się tymi wrażeniami podzielić. Jednak moje poszukiwania skończyły się na tych dwóch testach:

http://www.gotdotnet.com/team/compare/nileperf.aspx
http://www.shudo.net/jit/perf/



Programming Blogs - BlogCatalog Blog Directory
WordPress, Pool Theme - Borja Fernandez - mod