środa, 16 grudnia 2015

Dekompozycja projektu w R

Robiłem prezentacje i zastanawiałem się jak można zapisać cały projekt. Szukałem po sieci jakiś dobrych praktyk do dekompozycji plików. Ja wykombinowałem podział całego projektu na kilka plików:

Co w tych plikach jest? Zaczynając od początku:
Install.r - instalacja pakietów (ten skrypt wykonujemy tylko raz, aby pobrać paczki)
Functions.r - wszystkie funkcje
Load.r - ładowanie pakietów oraz przygotowywanie danych do prezentacji
Presentation.rpres - warstwa prezentacji, równie dobrze możne być to plik w Rmd czy z użyciem shiny (powód istnienia tego pliku jest TYLKO wyświetlanie tych danych jakie chcemy przedstawić, nie ma logiki biznesowej).
custom.css - customizacja warstwy prezentacji, czyli overridowane i dodatkowe css'y

I na końcu w folderze figures mam wszystkie zdjęcia.
Prezentacja o najpopularniejszych kryzysach ekonomicznych nie jest skończona. Jeszcze dużo chciałoby się dodać. Zaletą rpres jest to, że za każdym razem możemy mieć aktualne dane na prezentacji.
Poniżej rezultat wygenerowanej prezentacji:

wtorek, 13 października 2015

Program jak żarówka

Obejrzałem filmik dokumentalny o sztucznym wytwarzaniu rynku zbytu dla różnych produktów. Zastanawiam się czy można takie podejście zastosować do oprogramowania, które mogłoby działać jak lodówka, drukarka albo jak współczesna żarówka. Na przykład oprogramowanie może działać tylko przez 1000 godzin lub po danej liczbie uruchomień aplikacja będzie się zacinać. Klient takiej aplikacji będzie musiał zrobić update albo kupi nową wersję aplikacji (lub nowy sprzęt).

Po dłuższym zastanowieniu się to taki model biznesowy dla oprogramowania już występuje :)
W każdym razie, zapraszam do obejrzenia filmiku.



środa, 7 października 2015

Zmiana culture w bloku using

Bawiłem się kultura i potrzebuję kodu, który zostanie wywołany dla konkretnej kultury, a później wróci do poprzedniej kultury. Żeby to zrobić najprościej to należy użyć interfejsu IDisposable i tyle.
public class CultureContext : IDisposable
  {
      private CultureInfo contextCultureInfo = null;
 
      private CultureInfo exitCultureInfo = null;
 
 
   public CultureContext(CultureInfo ci)
   {
       exitCultureInfo = GetCulture();
       contextCultureInfo = ci;
       SetCulture(ci);
   }
 
   public void Dispose()
   {
       SetCulture(exitCultureInfo);
   }
 
      public virtual void SetCulture(CultureInfo ci)
      {
          Thread.CurrentThread.CurrentUICulture = ci;
          Thread.CurrentThread.CurrentCulture = ci;
      }
 
      public virtual CultureInfo GetCulture()
      {
          return Thread.CurrentThread.CurrentCulture;
      }
 
  }
Wtedy zastosowanie kultury w bloku using jest proste:
using (new CultureContext(new CultureInfo("en-US")))
{
      ...
}
Im prostsze rozwiązanie tym lepsze :)

poniedziałek, 5 października 2015

Walidacja bibliotek jako krok w CI

Skąd wież, że masz poprawne informacje w biblioteczce (.dll)?
Skąd wież, że wszystkie biblioteki w projekcie mają taką samą wersję lub nazwę produktu?
Ja napisałem mały skrypcik do walidacji biblioteczek pod względem wersji. Poniżej jest skrypt:
function Test-AssemblyVersion
{
    param(
        [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)
    ]
    [String]
    $filePath
    ,
    [Parameter(
        ValueFromPipeline=$false)
    ]
    [String]
    $ProductVersion
    ,
    [Parameter(
        ValueFromPipeline=$false)
    ]
    [String]
    $FileVersion
    )
    begin{
        $invIC= [System.StringComparison]::InvariantCultureIgnoreCase
    }
    process {
        $file = $_
        if(test-path $file)
        {
            $ass = [System.Reflection.Assembly]::LoadFile($file)
            $fvi = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($ass.Location)
            if( $ProductVersion.Equals($fvi.ProductVersion, $invIC) 
               -and  $FileVersion.Equals($fvi.FileVersion, $invIC) )
            {
                Write-Host "$file is ok."
            }
            else
            {
                throw "Wrong ProductVersion or  FileVersion in $file."
            }
        }
    }
}
Przykładowe wywołanie przedstawione jest poniżej:
gci -path .\MyProject\bin\ -recurse -filter 'MyProject.*.dll' | Test-AssemblyVersion -ProductVersion 2.1.0.0 -FileVersion 2.1.0.0
Można teraz dodać wywołanie i funkcję do jednego pliku i cały kod wyglądałby tak:
param(
[string]$ProductVersion, 
[string]$FileVersion
)
function Test-AssemblyVersion
{
    param(
        [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)
    ]
    [ValidateNotNullOrEmpty()]
    [String]
    $filePath
    ,
    [Parameter(
        Position=1, 
        Mandatory=$true, 
        ValueFromPipeline=$false,
        ValueFromPipelineByPropertyName=$false)
    ]
    [ValidateNotNullOrEmpty()]
    [String]
    $ProductVersion
    ,
    [Parameter(
        Position=2, 
        Mandatory=$true, 
        ValueFromPipeline=$false,
        ValueFromPipelineByPropertyName=$false)
    ]
    [ValidateNotNullOrEmpty()]
    [String]
    $FileVersion
    )
    begin{
        $invIC= [System.StringComparison]::InvariantCultureIgnoreCase
    }
    process {
        $file = $_
        if(test-path $file)
        {
            $ass = [System.Reflection.Assembly]::LoadFile($file)
            $fvi = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($ass.Location)
            if( $ProductVersion.Equals($fvi.ProductVersion, $invIC) -and  $FileVersion.Equals($fvi.FileVersion, $invIC) )
            {
                Write-Host "$File is ok. ProductVersion is $($fvi.ProductVersion) and FileVersion is $($fvi.FileVersion)"
            }
            else
            {
                throw "Wrong ProductVersion or  FileVersion in $file. ProductVersion is $($fvi.ProductVersion) and FileVersion is $($fvi.FileVersion)"
            }
        }
    }
}
$root  = ( gi  '..\..'  ).FullName
Write-host "Root is $root"
$OutputPackage = "$root\bin"
if(Test-path $OutputPackage)
{
    $fcraLib  = gci -path $OutputPackager -filter 'MyProject.*.dll' 
    if( $fcraLib)
    {
        $fcraLib | %{$_.Fullname} | Test-AssemblyVersion -ProductVersion $ProductVersion -FileVersion $FileVersion
    }
    else
    {
        throw "No dll files in dir: $OutputPackage "
    }
}
Teraz można ten skrypt podpiąć do TeamCity.

sobota, 3 października 2015

Usuwanie .DS_Store poraz n-ty

Zawsze jak commituje moje repo to przez przypadek dodaje pliki .DS_Store. Już tysiące osób pisało jak rekurencyjnie usuwać takie pliki, to ja też napisze.

sudo find . -name ".DS_Store"  -type f -depth -exec rm {} \;