czwartek, 5 marca 2015

[c# / csharp] Jak zainicjować listę w jednej linijce (inline) w "csharpie"

Inicjowanie listy w inline'owo

C# umożliwia nam zainicjowanie listy w jednej linijce (inline).
Już nie musimy pisać:

List list = new List();
list.Add("a");
list.Add("b");
list.Add("c");

ani robić lekkich haków z array
new List(new string[] { "a", "b", "c"});

wystarczy po prostu napisać:
new List { "a", "b", "c" };

natomiast lista z jakaś naszą klasą po prostu będzie wyglądać tak:

new List {

new User { Id = 1, Name = "UserName1" },

new User { Id = 2, Name = "UserName2"}

});

przyjemnie

środa, 4 marca 2015

Optymalizacja kodu w ruby

Parę ciekawostek odnośnie optymalizacji kodu w ruby

Czasem warto poznać różne "sztuczki" aby przyspieszyć aplikację napisaną w ruby. Przejdźmy od razu do rzeczy:

1. Zamiast używać begin..rescue podczas zabezpieczenia się przed NoMethodError można użyć Object#respond_to?(:metoda)
Przyspieszenie: 10x

2) Jeśli mamy posortowaną tablicę to użycie Array#bsearch zamiast popularnego Array#find przyspieszy niemalże "diabolicznie" ;) Array#find działa w taki sposób, że sprawdza warunek na każdym elemencie, natomiast Array#bsearch (przeszukiwanie binarne) znajduje środek a następnie sprawdza warunek czy wartość jest większa, mniejsza, równa wtedy podejmuje decyzję czy szukać środka w pierwszej części czy w drugiej. Szczegółowe wytłumaczenie można zobaczyć sobie tutaj: http://en.wikipedia.org/wiki/Binary_search_algorithm

3) Zamiast Hash#merge można zastosować Hash#merge! Działa to szybciej dlatego, że merge! wykona operację bez zbędnego kopiowania siebie samego.
Przyspieszenie: 25x

4) Losowa wartość z tablicy. Array#shufle.first - działa w taki sposób, że najpierw alokuje miejsce w pamięci dla kopii tablicy a następnie kopiuje losowo wartości. Jak widać musi sporo pracy wykonać. Zamiast "szufli", można skorzystać z Array#sample
Przyspieszenie: 17x

Ruby ma więcej takich rzeczy, postaram się wyciągnąć podobne, które rozsiane są po różnych konferencjach.

opracowane na podst. https://www.omniref.com/github/JuanitoFatas/fast-ruby/HEAD/files/Rakefile

niedziela, 1 marca 2015

Jak przyspieszyć inicjalizacje obiektów aby szybciej można było utworzyć listy, słownik danych

Jeśli potrzebujecie przechować jakieś dane np. w cache to najpierw je trzeba pobrać i gdzieś umieścić. Przedstawię mały trick. Większość programistów c# (dane wzięte z kosmosu, ale się domyślam, że tak jest) przechwycone dane zapisuje jako klasę by następnie przechowywać je w jakiejś strukturze danych (lista, słownik, tablica). To w większości przypadków jest OK, lecz wyobraźmy sobie, że mamy do zainicjowania kolekcję złożoną z baaaaaaardzo wielu elementów a zależy nam bardzo na szybkości inicjalizacji. Więc zamiast robić:

Enumerable.Range(0, 10000000).ToDictionary(k => k, v => new X(123));

gdzie X jest klasą

wystarczy utworzyć strukturę
        struct Y
        {
            public int Val;
            public Y(int val) {
                Val = val;
            }
        }


 Enumerable.Range(0, 10000000).ToDictionary(k => k, v => new Y(123));

U mnie wzrost wydajnościowy jest niemal 3-4 krotny.

ps oczywiście tytuł jest trochę mylący bowiem struktura (Struct) nie jest obiektem!

Podstawy optymalizacji w C#. Odszukanie elementu z dużego zbioru danych.

Słowniki danych (dictionaries), są używane gdy potrzebujemy bardzo szybkiego dostępu do danych w pamięci. Standardowo można użyć listy:

List users = new List();

....

list.Single(k => k.UserId == 1);

problem tutaj jest taki, że przepatrujemy cały zbiór do momentu aż natrafimy na element spełniający warunek. Jeśli UserId znajdowałby się na samym końcu to zostanie przepatrzona cała lista. Wyobraźmy sobie, ze potrzebujemy co chwilę wyciągać użytkowników po danym ID. Trochę to wypada kiepsko.

Dobrym rozwiązaniem jest skorzystanie np. ze słownika danych:

Dictionary users = new Dictionary();

users[201]; // zwraca użytkownika z UserId 201

działa to na prawdę bardzo szybko.

sobota, 28 lutego 2015

Programowanie serie książek dla początkujących / zaawansowanych

Istnieje na rynku kilka serii książek dla programistów, są to np. serie:

Head First - przeznaczone raczej dla początkujących programistów, ze względu na sposób tłumaczenia poszczególnych zagadnień. Oczywiście serie Head First poruszają przeróżne tematy nawet te zaawansowane, lecz niezbyt dogłębnie. Sposób tłumaczeń dla programistów będący w branży od jakiegoś czasu pozostawia wiele do życzenia. Np. w książce "head first wzorce projektowe" część przykładów jest wziętych z kosmosu. Klasyfikuję te pozycję dla początkujących ew. średniozaawansowanych. Mimo wszystko każdy może sobie poczytać HeadFirsta, ot choćby dla relaksu a nuż znajdziemy coś czego nie wiedzieliśmy.

Osobiście przeczytałem:

Chciałbym zaznaczyć, iż nie był to czas stracony, ABSOLUTNIE.Wiele się dowiedziałem, ale coż, byłem początkujacy. Wiele wyniosłem z HeadFirstów, lecz trzeba było się posiłkować innymi przykładami. Jedną rzeczą którą zapamiętam do końca życia z książki Wzorce Projektowe to "stopnie wtajemniczenia" ludzi poznających wzorce:
  • Początkujacy - widzi wszędzie wzorce i wdraża je tam gdzie się nawet źle sprawdzą
  • Średniozaawansowany - podchodzi już z większym dystansem, modyfikuje je do własnych potrzeb
  • Zaawansowany/Guru - stara się ich w ogóle nie nadużywać. Zawsze trzeba obierać najprostszą drogę do realizacji zadania. Z wzorców czerpie się inspiracje oraz poszerza swoje horyzonty.

O'Reilly Media - większość pozycji z tej serii prezentuje na prawdę bardzo dobry poziom. Jeszcze ani razu się nie zawiodłem na żadnej książce pochodzącej z O'Reilly. W serii można znaleźć książki na prawdę poruszający każdy temat:

  • Techniki optymalizacji stron internetowych na poziomie CSS, JS, konfiguracji serwerów
  • Konfigurowanie serwerów linux/windows i więcej
  • Najnowsze/Topowe technologie typu node.js, ruby 2.X
  • Prace z bazami danych - dosłownie każdą łącznie z bazami NoSQL (mongodb, cassandra itp.)
  • Uwaga! Radzenie sobie z Google SEO :)

Każdy znajdzie coś dla siebie. Książki mają charakterystyczne białe okładki, na których zawsze najdziemy jakieś (dziwne) zwierze.

Ostatnią serię na jaką chciałbym zwrócić uwagę jest seria:
Folwer - przeważnie są to czarne książki ze specjalnym znakiem "A Martin Fowler Signature Book". Przeznaczone dla osób szukających najlepszych rozwiązań oraz chcących się rozwijać. Poruszają bardzo trudne tematy, które nie tak prosto normalnemu programiście przyswoić. Czasem trzeba przeczytać jedną pozycję parę razy po kilku miesiącach wtedy całkowicie można zmienić swoje poglądy na temat wytwarzania oprogramowania. Dla ludzi interesujących się architekturą oprogramowania obowiązkową pozycja jest Patterns of Enterprise Application Architecture. Bogaty zbiór dobrych praktyk i wzorców, dogłębne omówienia zagadnień np. Unit of work, jak stworzyć własny ORM czy też jak radzić sobie z blokadami "optymistycznymi/pesymistycznymi", jaką architekturę dobrać do danego systemu i wiele więcej. A to tylko jedna z pozycji serii. Polecam ją każdemu kto nie chce być tylko programistą w biurze od 9 - 17 a projektowanie/programowanie jest jego pasją.

Warto napomknąć jeszcze serie Roberta C. Martina (aka Unlce Bob), lecz to zostawię sobie na osobny wpis.

wtorek, 20 stycznia 2009

[Rails] i18n, tłumaczenia, model, globalize2

[Rails >= 2.2.2]
Railsy dostarczają bardzo prosty a zarazem bardzo przydatny mechanizm i18n służący do tworzenia różnych wersji językowych. Na początku zainstalujemy sobie plugin globalize2.

./script/plugin install git://github.com/joshmh/globalize2.git

Dzięki temu teraz w modelu możemy określić jakie pola będziemy poddawać tłumaczeniom (translates), ale o tym za chwile.

Na wstępie skonfigurujmy sobie i18n. Konfiguracja odbywa się w pliku: config/enviroment.rb. Przejdźmy do linii 50, odkomentujmy ją usuwając "#"

jeśli linia u Was tak wygląda tak:

Config.i18n.load_path << Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]

to zmieńcie ją na:

Config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]

Odkomentujmy jeszcze 51 linię i ustawmy domyślny język strony na polski:

config.i18n.default_locale = :pl


[zrestarujmy aplikację]

Teraz zajmiemy się plikiem migracyjnym.
Utworzymy tabele z jakimiś regionami.

class CreateRegions < ActiveRecord::Migration
def self.up
create_table :regions do |t|
t.column :value, :integer, :null => false #jakąś wartość tutaj będziemy trzymać
end

#tabela z tłumaczeniami, nazwa jest bardzo ważna musi się kończyć na _translations
create_table :region_translations do |t|
t.string :locale #tutaj się określa język, 'pl', 'en', etc.
t.references :region #odwołanie do tabeli region kolumna region_id
t.string :name, :null => false, :limit => 50
end

#importujemy przykładowe dane
Region.create(:id => 1, :value => 123)
#dodajemy tlumaczenia
RegionTranslation.create(:locale => 'pl', :region_id => 1, :name => 'region polski')
RegionTranslation.create(:locale => 'en', :region_id => 1, :name => 'region angielski')

end

def self.down
drop_table :regions
drop_table :region_translations
end
end


Importujemy:

rake db:migrate

Przechodzimy do modelu Models/region.rb

class Region < ActiveRecord::Base
end


dodajemy translates:

class Region < ActiveRecord::Base
translates :name #jaka kolumna jest poddawana tłumaczeniom
end


To by było na tyle :) użyjmy teraz tego mechanizmu:

#Zapis:
I18n.locale = 'en' #ustawiamy jaki język chcemy
r = Region.new
r.id = 19
r.value = 'cos'
r.name = 'nazwa po angielsku'
r.save

#Select:
I18n.locale = 'en'
r = Region.find_by_id 19
p r.name #wypisze'nazwa po angielsku'


Jeśli chcemy zmienić język wystarczy przestawić I18n.locale = 'pl' :) czy można prościej?

Ustawmy jeszcze w kontrolerze, by za każdym razem przeprowadzał sprawdzenie jaki język chcemy.

plik: app/controllers/application.rb


dodajemy

before_filter :set_locale

def set_locale
session[:locale] = params[:locale] if params[:locale]

I18n.locale = session[:locale] || I18n.default_locale
end


Dopiszmy w config/routes.rb :locale do routingów
:controller/:action/:id' zamieniamy na :locale/:controller/:action/:id'

No i super nasz model może zawierać kilka wersji językowych, lecz co ze statycznymi tekstami na stronie? Typu:

app/views/home.erb:

<%= 'Cześć, witaj na mojej stronie :)' =>

Jak to zmienić na język angielski? Myślę że prościej na świecie się już na prawdę nie da.
Idziemy do katalogu: config/locales tworzymy tam 2 pliki, en.yml oraz pl.yml (zawierać będą tłumaczenia).

Na pierwszy ogień bierzemy pl.yml
pl:
home:
hello: "Cześć, witaj na mojej stronie :)"


a w en.yml wpisujemy
pl:
home:
hello: "Hi, welcome to my page :)"


przechodzimy z powrotem do app/views/home.erb i zmieniamy:

<%= 'Cześć, witaj na mojej stronie :)' =>

na

<%= t 'home.hello' =>

I wszystko działa jak należy :) Magia railsów ;)

Rubinowe szaleństwo

Tak, tak, dopadło mnie ... (nie)stety ;)

Dlatego postanawiam zmienić profil bloga. Teraz zamiast wytworów MS będę opierać posty o Ruby(OnRails).

Książki które warto kupić jeśli ktoś jest zainteresowany tematyką:

Ruby (od tego powinno się zacząć, trzeba poznać język bo się z railsami nie dogadamy ;) ):















Rails: