Category: Programowanie
Wszystko co związane z programowaniem
The Clean Architecture
Prezentacja wujka Boba na temat Clean Architecture
Główne założenia Clean Architecture
- Struktura projektu powinien odzwierciedlać architekturę, a nie użyty framework (Screaming Architecture).
- Elementy takie jak UI, serwer, baza danych, użyty ORM to szczegóły który powinny być ukryte
- Testowalność – reguły binzesowe można testować nieleżenie od UI, użytego serwera, bazy danych itd.
- Wykorzystanie Dependency Inversion principle
Więcej informacji:
Effective software delivery
Opis z YouTube: Podczas tej prezentacji przejdziemy przez poszczególne fazy dostarczania oprogramowania i odpowiemy sobie na pytanie jakie możliwości optymalizacji mamy do dyspozycji na poszczególnych etapach. Powiemy sobie jakich błędów unikać poczas prototypowania, jak wykorzystać specyfikę projektu i nie dać się ponieść pragnieniu rozwiązywania wszystkich problemów za pomocą złotego młotka. Poruszymy mit spowalniających development testów automatycznych, odpowiemy na pytanie czy DRY mówi tylko o unikaniu copy-paste w naszej aplikacji oraz przeanalizujemy szerzej zagadnienie przedwczesnej optymalizacji. Poznamy także narzędzia i techniki, która pozwalają nam efektywniej pracować nad wytwarzaniem oprogramowania.
Zasady dobrego programisty
Don’t Repeat Yourself (DRY) – nie powtarzaj się
Jest to jedna z najważniejszych zasad i powinniśmy traktować ją bardzo poważnie. Objawia się ona nie tylko powielaniem tego samego kodu i używanie metody Copy&Paste.
Single-Responsibility Principle (SRP) – zasada pojedynczej odpowiedzialności
Żadna klasa nie może być modyfikowana z więcej niż jednego powodu.
Jeśli jesteśmy w stanie wyobrazi sobie więcej niż jeden bodziec skłaniający programistę do zmiany klasy, mamy do czynienia z klasą rozciągającą się na więcej niż jeden obszar odpowiedzialności.*
Open/Close Principle (OCP) – zasada otwarte-zamknięte
Składniki oprogramowania (klasy, moduły, funkcje itp.) powinny być otwarte na rozbudowę, ale zamknięte dla modyfikacji.
Na początku może wydawać się to sprzeczne bo jak mamy wprowadzać zmiany skoro nie możemy modyfikować kodu. Odpowiedzią jest abstrakcja. W świecie obiektowym abstrakcje mają postać abstrakcyjnych klas bazowych, a grupa niezwiązanych, możliwych zastosowań jest reprezentowana przez klasy pochodne.
Moduł, który wykorzystuje abstrakcje, może być zamknięty dla modyfikacji, ponieważ jego działanie jest uzależnione właśnie od tej abstrakcji. Dzięki temu mamy możliwość rozszerzania tego modułu bez potrzeby modyfikacji jego kodu.
Liskov Substitution Principle (LSP) – zasada podstawień Liskov
Musi istnieć możliwość zastępowania typów bazowych ich podtypami.
Znaczenie tej zasady staje się oczywiste, kiedy rozważymy konsekwencje jej naruszenia. Przypuśćmy, że dysponujemy funkcją f, która otrzymuje za pośrednictwem swojego parametru referencję do pewnej klasy bazowej B. Załóżmy także, że przekazanie na wejściu funkcji referencji do klasy D (potomnej względem klasy B) powoduje błędne działanie tej funkcji. W takim przypadku klasa D narusza zasadę podstawienia Liskov (LSP). Oznacza to, że klasa D jest wrażliwa w kontekście funkcji f.
Prostym przykładem naruszenia tej zasady jest weryfikacja typów za pomocą instrukcji if-else
Dependecy-Inversion Principle (DIP) – zasada odwracania zależności
Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Obie grupy modułów powinny zależeć od abstrakcji.
Abstrakcje nie powinny zależeć od szczegółowych rozwiązań. To szczegółowe rozwiązania powinny zależeć od abstrakcji.
Interface Segregation Principle (ISP) – zasada segregacji interfejsów
Ma na celu wyeliminowanie nieporęcznych “grubych” interfejsów. Do tej grupy zaliczamy nadmiernie rozbudowane i niespójne interfejsy klas. Innymi słowy, interfejsy takich klas należy dzielić na mniejsze grupy metod. Każda taka grupa odpowiada za obsługę innego zbioru klientów. Oznacza to, że część klientów będzie korzystała z jednej grypy metod, podczas gdy pozostałe aplikacje klienckie będą korzystały z pozostałych grup metod.
Zasada skautów: Pozostaw obóz czyściejszym, niż go zastałeś.
(Staraj się pozostawić ten świat nieco lepszym niż go zastałeś)
Bibliografia:
- Agile Programowanie zminne, Robert C. Martin, Micah Martin
- Czysty kod, Robert C. Martin
The transaction log for db BizTalkMsgBoxDb is full.
SQL Server returned error string: “The transaction log for database ‘BizTalkMsgBoxDb’ is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases”.
Solution:
[sql]
sp_helpdb ‘BizTalkMsgBoxDb’
ALTER DATABASE BiztalkMsgBoxDb
SET RECOVERY SIMPLE;
GO
DBCC SHRINKFILE (BiztalkMsgBoxDb_log, 1);
GO
sp_helpdb ‘BizTalkMsgBoxDb’
GO
ALTER DATABASE BiztalkMsgBoxDb
SET RECOVERY FULL
GO
[/sql]
MSCRM 4.0 Web Service Toolkit (JavaScript)
CRM Web Service Toolkit jest małą JavaScript’ową biblioteką umożliwiającą łatwy dostęp do web serwisów Microsoft Dynamics CRM 4.0.
Dzięki niej możemy w szybki sposób:
- tworzć/aktualizować encje
- zmieniać stan encji
- tworzyć zapytania za pomocą fetchXML czy poprzez metodę RetrieveMultiple
- i wiele innych metod dostępnych w web serwisach CRMa
Przykłady
Encje tworzymy za pomocą metody CrmServiceToolkit.Create()
[js]
// Use CrmServiceToolkit. Create() to create a CRM contact record.
var contact = new CrmServiceToolkit.BusinessEntity("contact");
contact.attributes["firstname"] = "Diane";
contact.attributes["lastname"] = "Morgan";
contact.attributes["gendercode"] = 2;
contact.attributes["familystatuscode"] = 1; // Picklist : Single – 1
contact.attributes["creditlimit"] = 3000;
var createResponse = CrmServiceToolkit.Create(contact);
[/js]
CrmServiceToolkit.Retrieve() używamy do zwracania pojedynczych encji
[js]
// Use CrmServiceToolkit.Retrieve() to retrieve a CRM contact record.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var cols = ["firstname", "lastname", "familystatuscode", "creditlimit", "birthdate", "donotemail"];
var retrievedContact = CrmServiceToolkit.Retrieve("contact", contactId, cols);
alert(retrievedContact.getValue(‘lastname’));
alert(retrievedContact.getValue(‘firstname’));
// Picklist value (integer)
alert(retrievedContact.getValue(‘familystatuscode’));
// Picklist selected text
alert(retrievedContact.getValue(‘familystatuscode’, ‘name’));
// Currency field value
alert(retrievedContact.getValue(‘creditlimit’));
// Currency field formatted value (string)
alert(retrievedContact.getValue(‘creditlimit’, ‘formattedvalue’));
// Datetime field date/time value
alert(retrievedContact.getValue(‘birthdate’));
// Datetime field date string
alert(retrievedContact.getValue(‘birthdate’, ‘date’));
// Datetime field time string
alert(retrievedContact.getValue(‘birthdate’, ‘time’));
// Bit field value
alert(retrievedContact.getValueAsBoolean(‘donotemail’));
[/js]
Metoda CrmServiceToolkit.setState() umożliwia nam zmiane stany encji
[js]
// Use CrmServiceToolkit.setState() to update a CRM record status.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var response = CrmServiceToolkit.setState(‘contact’, contactId, ‘Inactive’, 2);
alert(response);
[/js]
CrmServiceToolkit.queryByAttribute() zwraca nam wszystkie rekordy spełniające podane kryterja.
[js]
// Use CrmServiceToolkit.queryByAttribute() to retrieve all CRM records that match the query criteria.
var queryOptions = {
entityName : "contact",
attributes : ["firstname", "lastname"], // Search by firstname and lastname
values : ["John", "Smith"], // Find all contacts whose firstname is John, lastname is Smith
columnSet : ["familystatuscode", "creditlimit", "birthdate"],
orderby : ["creditlimit", "birthdate"]
};
var fetchedContacts = CrmServiceToolkit.queryByAttribute(queryOptions);
[/js]
Więcej informacji na:
http://crmtoolkit.codeplex.com/
http://danielcai.blogspot.com/2010/07/crm-web-service-toolkit-for-javascript.html
MSCRM 4.0 Form Properties
Do pól formularza odwołujemy się poprzez obiekt crmForm:
[js]
crmForm.propertyname
[/js]
Tabelka poniżej przedstawia dostępne właściwości.
Właściwość | Typ | Opis |
IsDirty | bool | Określa czy formularz był modyfikowany |
FormType | int | Tylko do odczytu. Typ formularza.Możliwe wartości:
|
ObjectId | string | Tylko do odczytu. Identyfikator encji. Jeśli formularz jest w trybie edycji |
ObjectTypeCode | string | Tylko do odczytu. Kod typu encji którą edytujemy/wyświetlamy na formularzu |
ObjectTypeName | string | Tylko do odczytu. Nazwa typu encji której dotyczy formularz |
all.{field name} | Kolekcja poszczególnych pól formularza odpowiadającym polom w encji lub IFRAME formularza. |
Przykład
[js]
var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;
// Test the FormType and ObjectId properties.
switch (crmForm.FormType)
{
case CRM_FORM_TYPE_CREATE:
alert("This is a create form.");
break;
case CRM_FORM_TYPE_UPDATE:
alert("This is an update form, the ID is " + crmForm.ObjectId + ".");
break;
}
[/js]
[js]
var CRM_ENTITY_ACCOUNT = 1;
var CRM_ENTITY_CONTACT = 2;
// Test the ObjectTypeCode property.
switch (crmForm.ObjectTypeCode)
{
case CRM_ENTITY_ACCOUNT:
alert("This is an Account form.");
break;
case CRM_ENTITY_CONTACT:
alert("This is a Contact form.");
break;
}
[/js]
Żródło: http://msdn.microsoft.com/en-us/library/cc150873.aspx
Testy jednostkowe: testowanie zdarzeń
Ostatni natknąłem się na problem testowania zdarzeń. Sprawa niestety nie jest prosta na pierwszy rzut oka. Zdarzenia w aplikacji wywołują się asynchronicznie (nie wiemy dokładnie kiedy zdarzenie zajdzie) więc aby je przetestować musimy poczekać aż dane zdarzenie wystąpi i wtedy zweryfikować poprawność danych. Tak więc nasuwa się pytanie jak wstrzymać metodę testową aby czekała do momentu zajścia zdarzenia lub jeśli jest to wymagane zasygnalizowała nam, że czas na wykonanie zadania minął.
Bardzo przydatna w takich przypadkach okazuje się klasa Monitor i instrukcja lock. Cały mechanizm opiera się na zablokowaniu obiektu w metodzie testującej za pomocą metody Monitor.Wait i czekanie na odblokowanie go przez zdarzenie metoda Monitor.Pulse. Taka funkcjonalność w zupełności wystarcza na potrzeby testów jednostkowy, a prostota sprawia, że testy tworzymy w szybki sposób. Przyjdźmy do przykładu i zobaczmy jak to wszystko wygląda w praktyce.
[csharp]
[TestMethod()]
public void MyExampleEventTest()
{
MyApplication target = new MyApplication();
bool result = false;
target.TestEvent += (s, e) =>
{
//Do something
result = s is MyApplication
lock (this)
{
Monitor.Pulse(this);
}
};
int timeout = 1000;
lock (this)
{
if (!Monitor.Wait(this,timeout)) //Wait for Event
Assert.Fail("Time out");
}
Assert.IsTrue(result);
}
[/csharp]
W przedstawionym przykładzie wykorzystałem funkcję Wait która po określonym czasie kończy działanie. Oczywiście możemy użyć też innej wersji funkcji Wait np. bez podawania czasu, dzięki czemu metoda testujące będzie czekać do skutku czyli do momentu wystąpienia zdarzenia.
Jawna i niejawna implementacja interfejsu w C#
Interfejs klasy — w obiektowych językach programowania interfejs jest abstrakcyjną reprezentacją klasy pozwalającą na korzystanie z niej niezależnie od faktycznej implementacji. Interfejs pozwala na enkapsulację wielu różnych obiektów utworzonych w oparciu o odmienne klasy, które zawierają implementację wspólnego interfejsu. [wikipedia]
Interfejs dostarcza nam pewną funkcjonalność którą realizują klasy implementujące go, dzięki czemu możemy posługiwać się wyłącznie interfejsem aby zrealizować konkretne zadania bez konieczności zagłębiania się w kod znajdujący się za nimi.
Interfejsy w C#
W języku C# definiując interfejs posługujemy się słowem kluczowym interface, trzeba pamiętać że przy tworzeniu interfejsu nie używamy modyfikatorów dostępu, gdyż wszystkie elementy zawarte w interfejsie są publiczne. W interfejsach tworzymy jedynie definicje wybranych elementów które muszą zaimplementować klasy/struktury je implementujące.
Interfejsy mogą zawierać deklarację:
- metod
- właściwości
- zdarzeń
- indekserów
Interfejsy nie mogą zawierać stałych, pól, operatorów, konstruktorów, destruktorów i zagnieżdżonych typów. Nie mogą zawierać również statycznych elementów.
Interfejsy mogą dziedziczyć po jednym lub kilku interfejsach. Elementami implementującymi interfejsy są klasy lub struktury (mogą on implementować wiele interfejsów). W języku C# mamy również możliwość tworzenia generycznych interfejsów.
Niejawna implementacja interfejsu
Niejawna implementacja interfejsu jest najbardziej znaną formą implementacji. Polega ona na zaimplementowaniu publicznych elementów których definicje zawiera interfejs:
[csharp]
interface ISampleInterface1
{
void Print();
string Message { get; }
}
interface ISampleInterface2
{
void Print();
}
class SampleClass : ISampleInterface1, ISampleInterface2
{
// Zarówno ISampleInterface1.Print i ISampleInterface2.Print
// wywołają tą metodę
public void Print()
{
Console.WriteLine("Metoda Print");
}
private string _message = "";
public string Message
{
get { return _message; }
set { _message = value; }
}
}
[/csharp]
Jak widzimy nie ma tu żadnej magi implementujemy w klasie SampleClass metodę Print i właściwość Message z interfejsu ISampleInterface1 do której dopisujemy setter.
Jawna implementacja interfejsu
Aby jawnie zaimplementować interfejs musimy nazwę implementowanego elementu poprzedzić nazwą interfejsu:
[csharp]
class SampleClass : ISampleInterface1, ISampleInterface2
{
void ISampleInterface1.Print()
{
Console.WriteLine("ISampleInterface1.Print");
}
void ISampleInterface2.Print()
{
Console.WriteLine("ISampleInterface2.Print");
}
private string _message = "";
string ISampleInterface1.Message
{
get { return _message; }
}
}
[/csharp]
Dzięki jawnej implementacji mamy możliwość zaimplementowani dwóch metod o tej samej nazwie co czasami może być niezmiernie przydatne. Przy jawnej implementacji trzeba pamiętać, że nie możemy używać modyfikatorów dostępu. Z jawną implementacją wiąże się też kilka niedogodności: implementacje elementów interfejsu nie są widoczne w klasie implementujące, aby uzyskać do nich dostęp musimy posługiwać się konkretny interfejsem. W przypadku właściwości Message nie możemy dopisać settera gdyż dostaniemy błąd kompilacji.
Więcej informacji na temat interfejsów można uzyskać w:
Interfaces (C# Programming Guide), Explicit Interface Implementation, Explicit Interface Implementation Tutorial, Implicit and Explicit Interface Implementations, Design Guideline Update: Explicit Member Implementation, Interface layout, Interface (C# Reference),