stary-wpis
.net developers days – myśli zebrane
Value objects z DDD to fajna sprawa, nawet jeśli nie korzysta się z pełnego dobrodziejstwa które oferuje ddd, to warto wprowadzić przynajmniej część. Duża zaletą jest to że string który może się kryć z User.Firstname oraz User.Address i który normalnie możemy ze sobą porównać, nagle stanie się nie porównywalny ponieważ stringa ukryjemy w klasie UserAddress, a stringa odpowiedzialnego za Firstname ukryjemy w klasie UserFirstname i pomimo tego że w środku są to stringi, to dla kompilatora będą to dwie zupełnie inne typy, przez co nie da się ich ze sobą porównać. Dodatkową zaletą jest to, że podczas definiowania parametrów metody, czytelniej będzie czytać foo(UserFirstname name, UserAddress address){…} niż foo(string name, string address){…}
Wszyscy jesteśmy ludźmi i musimy się pogodzić z tym, że czasem coś nam nie wyjdzie – musimy się z tym pogodzić. Nie warto zakładać, że wszystko co robimy skończy się spektakularnym sukcesem i nie każdy z nas skończy tak jak Marek Zuckerberg czy inne Grycanki. Czasem słońce, czasem deszcze – takie jest życie.
Breakstorming – fajna pomysł nie tylko dla testerów. Pracujecie w zespole? Spotkajcie się od czasu do czasu, ale nie za rzadko i zróbcie sobie code review, gdzie główną ideą jest zepsucie kodu innego kolegi; na zasadzie: pacz Stefan, jak wyślę takie parametry i wystąpi taki warunek, to twój serwis rzuca wyjątkiem. Można wymyślać najbardziej złośliwe ścieżki, najmniej prawdopodobne do spełnienia, etc. Chodzi o możliwie najefektywniejsze wysadzenie jeźdźca z siodła
Nie ładować konfiguracji podczas wykonywania kodu – już spieszę ze szczegółami. Chodzi o przypadek, gdy ustawienia miałby być ładowane przez samą metodę podczas wykonywania kodu. Czyli mogłoby dojść do sytuacji, że metoda foo(“jarek”, “wrocław”){…} raz wykona logikę_1 a raz wykona logikę_2, ponieważ pomiędzy poszczególnymi wywołaniami metod, plik z konfiguracją został zmieniony i teraz zachowuję się inaczej. Prowadzi to do niespójności w aplikacji. Konfiguracja powinna być zaczytana raz na początku działania aplikacji i tyle. Aby zmienić ustawienia, należy wykonać restart aplikacji.
Robiąc sobie zdjęcie ze Scottem :):):):) patrz na górze, doszły mnie słuchy, że przygotowywane są learniing box dla nowego asp i mvc na poziomie novice, regular, master – i powinny być oficjalnie dostępne w styczniu 2016 roku. Mają umożliwić samokształcenie jak i przygotowanie sesji dla innych ludzi. Wersje novice są chyba na mva. Nie szukałem więc nie posiadam linka.
Konferencja DevDay – moje złote myśli wyniesione
Byłem na DevDay2015!
Prezentacje były i można oglądać, albo będzie można wkrótce. Część ludzi spotkała się z ogromną ilością swoich fanów, inni leczyli kaca, inni słuchali i starali się coś z tego wyciągnąć. Jako że nie zapiłem, to starałem się coś mądrego usłyszeć, poniżej materiał zebrany i w mojej interpretacji:
Decyzje które podejmujesz podczas wybierania frameworka, biblioteki, pracownika, czy czegokolwiek innego powinieneś przemyśleć pod kątem, nie tylko rozwiązania, które przyniesie, a raczej odpowiedzialności, jaka zostanie na ciebie zrzucona. To nie wszystko, gdy znajdziesz rozwiązanie idealnie pasuje do twojego problemu, znajdź inne narzędzie które też rozwiąże ten problem i porównaj zady i walety obu. Upewnij się że ciężar wybranego przez ciebie rozwiązania jest akceptowalny. Jeśli chcesz być dobrym strategiem, architektem, rekruterem, pomyśl jakie problemy sprawi świeżo wybierana technologia i znajdź kolejne rozwiązanie tego problemu – uwaga na rekurencję.
TL;DR; decyzje które podejmujesz to nie tylko rozwiązanie, ale przede wszystkim konsekwencje
Każdy kod który tworzysz, nie zależnie czy jest to metoda, klasa, projekt, czy wszystko powinien być tak duży/mały aby rozwiązywał jeden i tylko jeden problem. Wiadomo SRP i takie. Ale jest jeszcze jedno spostrzeżenie: ten mały kod rozwiąże twój problem i fajnie, ale jeśli coś będzie z nim nie tak, wtedy kod psuć tylko tą jedną małą rzecz – nic więcej. SRP FTW! Ma ktoś taki tatuaż?
TL;DR; mały kod, małe projekty, małe serwisu. Jeśli będzie fakup, to rozwali tylko małą część twojej aplikacji lub systemu.
Wunderlist taka rozbudowana aplikacja todo – architektura opiera się o kilka(naście) technologi, każda klasa jest osobnym serwisem, komunikacja po http/rest. Rozwiązanie daje mega skalowalność, łatwo jest serwisy aktualizować, zmienić i wszystko. Całkiem interesujące podejście do całkiem sporego projektu. Bardzo mnie kusi bliższe poznanie jak to się robi, jak się z tym żyje i pracuje. Sama idea do mnie bardzo przemawia.
Poza tym, pogadałem i napiłem się piwa ze takie osobnikami jak Chris Heilmann,Scott Allen czy Chad Fowler – co też daje fajne wrażenia, że takie ważne osoby też piją piwo i też są ludźmi – kto by pomyślał. Oprócz nich poznałem kilka nowych osób, czy też dopoznałem innych.
Lubię hackatony
13 czerwca byłem na kolejnym. Art of code – świetna impreza, gdzie temat przewodnim była sztuka. Razem z zespołem Marcel, Michał, Łukasz stworzyliśmy aplikację która przy pomocy wolframa rozpoznawała zdjęcia, które jej wysłaliśmy, zwracała nam listę słów opisujących obraz. Następnie szukaliśmy synonimów. Aby następnie odegrać dźwięki na podstawie zwróconych słów. Chcieliśmy stworzyć nastrój do obrazu.
Kod dostępny jest na githubie:
https://github.com/jstadnicki/HearTheImage
Wszystko szlo pięknie do momentu, gdy trzeba było uruchomić aplikację. Okazało się że BASS, bibliotek do dźwięków którą chcieliśmy zaprząc do grania, odmówiła posłuszeństwa. Dosłownie minuty przed oddaniem projektów – świnia! Media player to nie chciał grać, musieliśmy więc rzucić ręcznik.
Suma sumarum, świetna impreza, świetni ludzie, świetna organizacja – gorący klimat (to jedyny minus). Jeśli będzie kolejna edycja, na pewno się zapisze.
Przy okazji, za dwa tygodnie organizujemy własny, trochę mniejszy niż ten, ale równie gorąco zapraszam, więcej informacji pod linkiem:
http://www.meetup.com/PGS-Software-Talks/events/223148590/
http://softwaretalks.pl/events/event/dev-qa-hackathon/
Autofac update – dynamiczna zmiana implementacji
1: [HttpGet]
2: public ActionResult Register()
3: {
4: var viewmodel = new RegisterViewModel();
5: return this.View("Register", viewmodel);
6: }
7:
8: [HttpPost]
9: public ActionResult Register(RegisterDto dto)
10: {
11: this.accountService.Register(dto);
12: return this.RedirectToAction("Index");
13: }
1: public void Register(RegisterDto dto)
2: {
3: WebSecurity.CreateUserAndAccount(
4: dto.Email,
5: dto.Password);
6: }
1: public class RegisterDto
2: {
3: public string Email { get; set; }
4: public string Password { get; set; }
5: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, “Courier New”, Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
1: [HttpGet]
2: public ActionResult NewUsers()
3: {
4: this.testService.CreateNewUsers();
5: return this.RedirectToAction("Index");
6: }
1: public void CreateNewUsers()
2: {
3: var dto = new RegisterDto
4: {
5: Email = Faker.InternetFaker.Email() + Faker.NumberFaker.Number(),
6: Password = Faker.NumberFaker.Number(1000000000, 2000000000).ToString()
7: };
8: this.accountService.Register(dto);
9: }
1: [HttpGet]
2: [Authorize]
3: public ActionResult NewBlogPost()
4: {
5: var viewmodel = new BlogPostViewModel();
6: return this.View("NewBlogPost", viewmodel);
7: }
8:
9: [Authorize]
10: [HttpPost]
11: public ActionResult NewBlogPost(NewBlogPostDto dto)
12: {
13: this.postingService.NewBlogPost(dto);
14: return this.RedirectToAction("Index");
15: }
1: public void NewBlogPost(NewBlogPostDto dto)
2: {
3: var userId = this.accountService.GetCurrentLoggedUserId();
4: var model = new BlogPost(userId, dto.Text, DateTime.Now);
5: this.database.BlogPosts.Add(model);
6: this.database.SaveChanges();
7: }
1: public class NewBlogPostDto
2: {
3: public string Text { get; set; }
4: }
1: class WebSecurityAccountService : IAccountService
2: {
3: public void Logout()
4: {
5: WebSecurity.Logout();
6: }
7:
8: public bool Login(LoginDto dto)
9: {
10: var result = WebSecurity.Login(dto.Email, dto.Password);
11: return result;
12: }
13:
14: public void Register(RegisterDto dto)
15: {
16: WebSecurity.CreateUserAndAccount(
17: dto.Email,
18: dto.Password);
19: }
20:
21: public int GetCurrentLoggedUserId()
22: {
23: return WebSecurity.CurrentUserId;
24: }
25: }
1: [HttpGet]
2: public ActionResult NewPosts()
3: {
4: this.testService.CreateNewPosts();
5: return this.RedirectToAction("Index");
6: }
1: public void CreateNewPosts()
2: {
3: var users = this.database.Users.ToList();
4: var random = users.ElementAt(Faker.NumberFaker.Number(users.Count - 1));
5: var dto = new NewBlogPostDto
6: {
7: Text = Faker.TextFaker.Sentences(3)
8: };
9:
10: SpecialAccountService.CurrentLoggedUserId = random.Id;
11:
12: this.postingService.NewBlogPost(dto);
13: }
1: public class SpecialAccountService : IAccountService
2: {
3: private readonly WebSecurityAccountService realAccountService;
4:
5: public SpecialAccountService()
6: {
7: this.realAccountService = new WebSecurityAccountService();
8: }
9:
10: public void Logout()
11: {
12: this.realAccountService.Logout();
13: }
14:
15: public bool Login(LoginDto dto)
16: {
17: return this.realAccountService.Login(dto);
18: }
19:
20: public void Register(RegisterDto dto)
21: {
22: this.realAccountService.Register(dto);
23: }
24:
25: static public int CurrentLoggedUserId { get; set; }
26:
27: public int GetCurrentLoggedUserId()
28: {
29: return CurrentLoggedUserId;
30: }
31: }
1: public class HijackService : IHijackService
2: {
3: public void RestoreIOC()
4: {
5: var builder = new ContainerBuilder();
6: builder.RegisterType<WebSecurityAccountService>().As<IAccountService>();
7: builder.Update(ApplicationIocContainer.Container);
8: }
9:
10: public void HijackIOC()
11: {
12: var builder = new ContainerBuilder();
13: builder.RegisterType<SpecialAccountService>().As<IAccountService>().SingleInstance();
14: builder.Update(ApplicationIocContainer.Container);
15: }
16:
17: public IOCStatus GetStatus()
18: {
19: var isHijacked = ApplicationIocContainer.Container.Resolve<IAccountService>() is SpecialAccountService;
20: return isHijacked ? IOCStatus.Hijacked : IOCStatus.Normal;
21: }
22: }