Flaksator – wprowadzenie

Zabawnie zbiegły się w jednym czasie interesujące okoliczności – Maciej Aniserowicz ogłosił kolejną edycję konkursu Daj się poznać, ja miałem ochotę wrócić do pisania a do tego odgrzebałem źródła jednego starego projektu – parodystycznego generatora tekstów piosenek black/death metalowych.

Zastanawiałem się jeszcze nad wznowieniem tworzenia Anonimizatora, ale póki co nie mam wystarczająco weny do tego – a bardziej zewnętrznej motywacji, ale głównie dlatego, że wznowiłem prace nad jeszcze innym, prehistorycznym projektem… Początkowo zastanawiałem się, czy nie pisać o niem, ale warunki konkursu (projekt open-source) go dyskwalifikują, mimo, że IMHO jest najciekawszy – ale to jest z założenia projekt o zamkniętym bazowym kodzie, za to otwarty na rozszerzanie. Ale pewnie i tak w jakiejś postaci prędzej czy później się tutaj pojawi 🙂

Tymczasem. Czym jest Projekt Flaksator? Jest to aplikacja oparta o moją wymyśloną (głównie) na jej potrzeby bibliotekę “Foneksator” do odmieniania części mowy przez przypadki, osoby itd. To nie miało być rozwiązanie do sprawdzania poprawności pisowni / gramatyki. Absolutnie. Założenie było takie by mając wybrany wyraz z bazy dostępnych słów zapisać go w potrzebnej odmianie. Za natchnienie posłużyły rozmaite prymitywne generatory białych wierszy i tekstów piosenek, ale bazujące jednak na sztywnych bazach wyrazów – a ja chciałem bardziej zróżnicowanych wyników. Poza tym było to całkiem zabawne, zwłaszcza po prowadzeniu do słownika wyrazów zupełnie od czapy.

Przykładowy wygenerowany tekst utworu:


[1.0] DARMOWY BLIŹNI
Wyjmuję miecz, robię zamach i mierzę w Ciebie,
To Twe ostatnie chwile, już za moment będziesz w niebie.
Chwyciłem mózg w dymającym smoczku,
Nadejdą dziś dziewicy polimorficzne fale.

(Refren)
W Twych duszach widzę tłuste gardło,
Dusząc Cię nie gryzie mnie jednak smoczysko.
Dostrzegłem ciało, doniczkę dziada,
Nie, nie zawiodę dziś mego doktora.
Już Cię widzę, jeszcze poranek, jeszcze frytka,
Ja już czuję jak bagno me się w Ciebie wbija.

Rzucasz mi się u nocy na ostrza o jęk mnie błagając,
Mnie to nie rusza, "Zginiesz jak Pan!" - krzyczę, trumną Cię przebijając.
Pancerz mroku w moich aparoskopiach,
Delektuje się w Twoich kaczuszkach.

(Refren)
W polnym odbycie dziś morduję,
skarbników, inkubów i inne śrubki.
Czuję Twój strach gdy ostrze me podąża wzdłuż Twej twarzy,
Woń flaków Twych, jelit, serca, płuc, podnieca mnie, ich dotyk parzy.
Rzucasz mi się u gnid na zwłoki o flak mnie błagając,
Mnie to nie rusza, "Zginiesz jak Yeti!" - krzyczę, lobotomią Cię przebijając.

Nastąpił świat zastanawiania,
Nadszedł już zew zabijania.
Jesteś w mej jatce, czas zmówić zielonego afrodyzjaku,
To już Twój zew, pochłonie Cię zombiaka kwiat.

Umywalki Twoje wezwały mnie,
Omamowi doktorowej nie powiem nie.
Znalazłem skrzep mojego wroga,
Wbiję go w łba mego sukuba.

Continue reading Flaksator – wprowadzenie

[Programming] Shared Context Pattern

In this post I would like to share with you very specific Data Connection Creation Pattern that I’m using in some form from many months. I’d already tested it with Entity Framework, MS Dynamix CRM, LinqToSQL and directly with plain ADO / MS SQL connectivity (and mixes of them). It went through several customizations and variations of course, but the whole idea is always the same.

DISCLAIMER: But before I go further I must first warn you, that I’m not a great fan of generic DI/IoC containers, Service Locator or creating thousands unnecessary interfaces only “in case of testing”. I prefer straight approach of direct dependencies and creation, clear and visible instance ownership, optimized lifetime management and code being primarily effective and easy to debug over working magically according to some god-class. While I consider myself primarily backend (workflow / batch / server processing) developer you should not be surprised that I sometimes micro-optimize my design from the beginning, not only after observing performance problems – it’s on purpose – I need my background tasks to not waste nor CPU neither memory to effectively process thousands Work Items at once.
I also do recommend reading this book: Writing High-Performance .NET Code to better understand why I’m sometimes doing what I’m doing (or not 🙂 )

This particular pattern has been influenced by trying to replace and join together in an effective manner some ideas implemented by such (anti)patterns like Repository, Item of Work, Service Locator and so. My core idea was to precisely:

  • control Data Access in heavily multi-thread processing environment,
  • keep it to be as lightweight as possible,
  • present to the user (in this situation – developer who will be utilizing this pattern) simple, functional and clean interface that he can intuitively work with.

Core implementation

Depending on project I’ve been using this patter, I’d been incorporating more or less interfaces, but at least two of them were always present:

  • ISharedContextFactory – responsible to cache data (and sometimes more) needed to connect to Data Source; and most of the time presenting two methods: CreateContext(), CreateReadOnlyContext() – both returning IDisposabled instance of a second interface:
  • ISharedContext – this interface gives the only access to instances of all known repositories through read-only accessors (properties). Depending on environment support it might also contain two methods: Commit() and Rollback() that are expected to finish whole item-of-work with desired output.

Continue reading [Programming] Shared Context Pattern

[Visual Studio] Fixing annoying bug [code 5455]

(Piszę ten post po angielsku bo może interesować dość szerokie grono odbiorców… A nie zajmuję się w nim jakąś wielką filozofią by nie wystarczyła podstawowa znajomość lengłydża.)

Today, when I’d started my PC after yesterday’s Windows 7 / Office updates I started my VS 2013 Update 3 and tried working on some project. But whenever I tried opening file with code I’ve been given a strange error message. From the message it looked like some problems with settings. So I tried to make a screenshot of the error window (because of locking focus) and pasted it into MS Paint. This is what I’ve got:
Error_Message

Ok, I had my phone with me so I was able to work around the issue:
Error_Message_Camera

Now I was able to go to the Options and try to find what might cause it. Unfortunately most of tabs had not been working and some (“All Languages” if I recall correctly) even caused VS to restart… Then I decided to reset all settings. And then I received something similar to what was described several months ago in following ticket:
Cannot open any code files

When I try to open up a C# code file an error pops up. The error that occurs states that “No EditorOptionDefinition export found for the given option name: Adornments/HighlightCurrentLine/Enable Parameter name: optionId”
I tried to reset my settings but I then received the following error “Your settings were reset, but there were some errors.
Error 1: Task List Display Settings: The tasklist format has changed.
Error 2: An error occurred while importing settings for ‘All Languages’ [code 5455&#93.
Error 3: An error occurred while importing settings for ‘Basic’ [code 5455&#93.
Error 4: An error occurred while importing settings for ‘C/C++’ [code 5455&#93.
Error 5: An error occurred while importing settings for ‘CSS’ [code 5455&#93.
Error 6: An error occurred while importing settings for ‘C#’ [code 5455&#93.
Error 7: An error occurred while importing settings for ‘CoffeeScript’ [code 5455].
Error 8: An error occurred while importing settings for ‘F#’ [code 5455&#93.
(…)
Error 18: An error occurred while importing settings for ‘XAML’ [code 5455&#93.
Error 19: An error occurred while importing settings for ‘XML’ [code 5455&#93.”

(I added a bit of formatting to exaggerate core issues.)

Continue reading [Visual Studio] Fixing annoying bug

Kilka pomysłów na kod, który łatwiej zrozumieć

Ostatnio dość sporo siedziałem w starym, odziedziczonym kodzie – nie tylko cudzym, ale i swoim. Sporo czasu zeszło mi na próby zrozumienia co autor miał na myśli… Na szczęście mogłem sobie pozwolić na wykonanie odpowiedniej refaktoryzacji z marszu – ok, część tego czego się domyśliłem umieściłem tylko w komentarzach ale tam gdzie się dało usprawnić kod od ręki – tam to zrobiłem.

Przy tej okazji chciałbym się podzielić kilkoma koncepcjami: zarówno starymi i dobrze znanymi jak i kilkoma, na które wpadłem – niekoniecznie ostatnio – zastanawiając się jak można pewne rzeczy sformułować lepiej… Ogólny zamysł przyświecającym tym ideom jest jeden – łatwiej zrozumieć co się dzieje w kodzie, także przy ewentualnym braku wsparcia ze strony VS (np. podczas łączenia gałęzi w repozytorium kodu…) gdy kod jest samo-dokumentujący. Że banał? Jasne. Tym niemniej zapraszam do lektury.

Magiczne liczby

Wszyscy niby wiemy, że magiczne numerki są złe. Bardzo złe… Dość oczywiste przykłady:

string libName = columnData.Substring(20, 13);
Item itm = collection.GetElementAt(indexRequested - 1);
// ...

Takie rzeczy zwykliśmy załatwiać za pomocą stałych, odpowiednich komentarzy, obiektów z konfiguracją itp.

Ale wszystkie one kręcą się wokół jednej rzeczy – co oznacza dany argument – skąd jego wartość, co ona oznacza dla aplikacji. Czyli np. w drugim przykładzie “1” oznacza (zazwyczaj) “korektę między systemem numeracji kolekcji, z którego korzysta algorytm dostarczający wartość zmiennej “indexRequested” do systemu numeracji wykorzystywanego przez samą kolekcję “collection“. W pierwszym przykładzie mamy jednak już dwa problemy jednocześnie – nie tylko co oznaczają podane argumenty ale jaką rolę pełnią odpowiednie parametry w wywołanej funkcji? (Ok, Susbstring() jest trywialnym przykładem – wszyscy ją znamy, ale chodzi mi o zasadę :P).

Czasami rozwiązując pierwszy problem, możemy jednocześnie rozwiązać i drugi. Np. w ten sposób:

string libName = columnData.Substring(libColumnDefinition.StartIndex, libColumnDefinition.Width);

Jednocześnie pozbywamy się magicznych liczb i umieszczamy je w konfiguracji (nawet jeśli nadal jest ona zakodowana na sztywno, to będąc trzymaną w jednym miejscu niesie o wiele więcej spójnej informacji) ale jednocześnie wskazujemy na znaczenie poszczególnych wartości dla Funkcji Substring().

Są jednak przypadki, gdy usunięcie magicznej liczby nie jest za bardzo możliwe. Np.

Timespan serviceTimeout = configuration.GetServiceTimeout(this.ServiceName) ?? new Timespan(0, 10, 0);

Continue reading Kilka pomysłów na kod, który łatwiej zrozumieć

O obsłudze sytuacji wyjątkowych słów kilka

Podczas jednej z niedawnych rozmów rekrutacyjnych (w sumie to chyba lubię na nie chodzić – często są dość inspirujące 🙂 ) spotkałem się z ciekawym pytaniem – “Jakie są negatywne konsekwencje stosowania konstrukcji try-catch?” Oczywiście zbyt wiele klawiatur zjadłem, by w ciemno walnąć głupotą, że są wyłącznie same zalety. Pominę co wtedy dokładnie odpowiedziałem, ale moja własna odpowiedź skłoniła mnie by jeszcze trochę pod tym kątem pogrzebać…

Trochę postów, trochę artykułów, sprawdzenie treści kilku książek. Wygląda na to, że ten teren nie jest jeszcze zbyt dokładnie spenetrowany… Mam swoją tezę do udowaodnienia – że jeśli już się decydujemy na przechwytywanie wyjątków to czeka nas ogromna ilość planowania i pracy. Tym artykułem postaram się ją udowodnić oraz podać kilka wskazówek jak można by zabrać się do realizacji tego zadania, o czym może warto pomyśleć z wyprzedzeniem.

Jednak na początek trochę rozważań teoretycznych i to zaczynając od poziomu bardziej abstrakcyjnego. Autor (Patrick Cauldwell) książki „Code Leader” (Amazon.com) dość jasno formułuje zasadę prezentowania sytuacji wyjątkowych użytkownikowi:

Errors should only be handed off to the user if there is something that the user can do to correct the problem, and that needs to be clearly communicated. (…) It is vitally important to make your error messages to the user actionable. If an error message doesn’t tell the user how to correct the problem, then there is no point in showing the user an error message.

Oczywiście po takim oświadczeniu natychmiast powinna nastąpić gorąca debata wśród architektów i programistów:

  • które błędy prezentować?
  • co robić z błędami których nie prezentujemy?
  • co zrobić z samą aplikacją po prezentacji błędu? Zwłaszcza z przetwarzanymi danymi?
  • które sytuacje to faktyczne wyjątki, a które to łatwe do przewidzenia sytuacje nieprawidłowości?
  • które błędy – ostatecznie – należy uznać za krytyczne i zagrażające porządkowi publicznemu?

Continue reading O obsłudze sytuacji wyjątkowych słów kilka

[Od rzeczy] Dziwna reklama

Otóż dotarło do mnie takie coś (jakość oryginalna):

Oryginalna treść reklamy

Reklama jak reklama, tablet jak to tablet ze średniej półki – poznęcam się nad nim dalej – ale mnie w pierwszej kolejności zastanowiła rola modelki na zdjęciu. Przyjrzyjmy się Pani bliżej – strona producenta dostarcza obrazek w dużo lepszej jakości:

Girl_from_advert_original

Nie mam pojęcia kto i dlaczego zatwierdził ten obrazek – dziewczyna jest nawet ładna ale (przynajmniej w wersji z mailingu) strasznie chuda. Chciałoby się powiedzieć – zabiedzona. To jakaś analogia do biedy reklamowanego sprzętu czy co? A do tego wygląda jakby została mocno uderzona w lewy policzek – sina skóra, oko odpadnięte i lekko zezujące w bok, jakby spuchnięta i ściągnięta połówka ust… Hmmm, czyżby reklama możliwych bojowych zastosowań sprzętu?…

Ale do rzeczy – Czy możliwa jest aż taka asymetria twarzy? Niemalże ma się wrażenie, że została sklejona z dwóch rożnych osób… Zobaczmy…

Dziewczyna z reklamy - porównanie asymetrii

Huh! – niemal zupełnie dwie rożne osoby, dwa rożne zdjęcia, inny układ świateł – co najmniej jak dwie siostry.
Mam nadzieje, że to tylko graficy / fotograf spartolili światła i robotę i coś namieszali. Oraz, że ta ładna dziewczyna na co dzień tak nie wygląda… Szkoda by było…


Wracając do samego sprzętu (Sorry, ale oryginalne formatowanie to jakieś masakryczne zabawy DIVami, więc cytuję po mojemu)…

Continue reading [Od rzeczy] Dziwna reklama

Dane wrażliwe

Dane osobowe to szeroki temat, jakkolwiek szeroko lub wąsko rozumiany – dla wielu wrażliwych jest to temat bardzo drażliwy. Jednak niezależnie od tego jak bardzo dana osoba przejmuje się bezpieczeństwem czy poufnością danych powierzonych innym podmiotom (świadomie czy nie) to jednak ustawa na każdego administratora danych osobowych nakłada obowiązek takiego ich przetwarzania, przechowywania i transmitowania by ich spójność i bezpieczeństwo były gwarantowane (i zgodne z ustawą – bla, bla, bla).

Część danych pozwala na jednoznaczną identyfikację osoby (lub podmiotu), której dotyczą. Są to unikalne identyfikatory typu PESEl, NIP, czy REGON. Mniej oczywiste są identyfikatory typu nazwa / imię i nazwisko – które w skali globalnej wcale nie muszą być unikalne. Podobnie poszczególne fragmenty adresu zamieszkania / korespondencyjnego nie muszą precyzyjnie wskazywać konkretnej osoby lub grupy osób (pomijając nawet zmienność i rozbieżność takich danych w czasie – ludzie i firmy często zmieniają miejsce zamieszkania / prowadzenia działalności– także jeden adres może być współdzielony przez wiele podmiotów) ale już w połączeniu z imieniem i nazwiskiem lub datą urodzenia mogą zawęzić zbiór potencjalnych osób do jednego człowieka.

A nawet jeśli nie – to wskazanie konkretnej grupy osób (np. rodziny) może już być odebrane jako pogwałcenie prywatności. Należy bardzo uważać przy łączeniu danych – może się zdarzyć, że połączenie częściowo zamaskowanego adresu (np. do poziomu nazwy ulicy, ale już bez numerów mieszkań) z samym tylko faktem posiadania ubezpieczenia medycznego w konkretnej firmie może precyzyjnie identyfikować konkretną osobę! (A najprawdopodobniej nazwa firmy ubezpieczeniowej nie będzie podlegać anonimizacji, ze względu na wymagania biznesowe systemu testowego…)

Oczywiście, jeżeli wiemy, że dane w całej bazie zostały zanonimizowane wówczas wiemy, że wszelkie próby statystycznego zestawiania poszczególnych elementów nie mają wielkiego sensu. Pod warunkiem wszakże, że poziom anonimizacji jest wystarczający. Wydaje się, że można próbować wskazać właściwe poziomy minimalne dla poszczególnych danych. W wielu przypadkach okaże się, że można zwiększyć te poziomy, gdyż zbyt szeroki zakres realnych danych nie będzie potrzebny podczas korzystania z bazy de-identyfikowanej (np. adresy pozostaną prawdziwe do poziomu miast, związanego z testowanymi zapytaniami raportowymi). Losowa de-identyfikacja ma jedną zasadniczą wadę – może tworzyć osobowości, które fragmentarycznie odpowiadają prawdziwym podmiotom – imiona, nazwiska czy numery PESEL nie mają jakiejś gigantycznej zmienności. Jednym z wymogów może być, by wylosowane wartości anonimizacyjne były różne od oryginalnych. Ale już sprawienie by nie były identyczne z innymi w systemie – niekoniecznie. Pewnym problemem mogą okazać się indeksy unikalne (np. na PESEL, czy niepoprawny na kombinacji imienia i nazwiska), które uniemożliwią takie duplikaty – aplikacja powinna być przygotowana na taką ewentualność i albo sprawdzać to z góry (konfiguracja) albo przechwytywać stosowny wyjątek i losować nową wartość.

Wróćmy zatem do listy proponowanej przez HIPPA:

Continue reading Dane wrażliwe

Anonimizacja vs de-identyfikacja

W pierwszej kolejności należałoby się zapoznać z różnicami między anonimizacją i de-identyfikacją.
Wg definicji (De-identification):

Anonymization
refers to irreversibly severing a data set from the identity of the data contributor in a study to prevent any future re-identification, even by the study organizers under any condition.
De-identification
is the process used to prevent a person’s identity from being connected with information. Common uses of de-identification include human subject research for the sake of privacy for research participants. Common strategies for de-identifying datasets are deleting or masking personal identifiers, such as name and social security number, and suppressing or generalizing quasi-identifiers, such as date of birth and zip code. The reverse process of defeating de-identification to identify individuals is known as re-identification.

Jak należy to rozumieć?

Anonimizacja
odnosi się do NIEODWRACALNEGO pozbawienia zbioru danych wszelkich wskazówek pozwalających na re-identyfikację osoby, której dotyczą.
De-identyfikacja

to usunięcie z danych wszelkich informacji OSOBISTYCH bezpośrednio lub pośrednio wskazujących na konkretną osobę, ale pozostawienie identyfikatora umożliwiającego ewentualne połączenie z oryginalnym zbiorem i osobą.

Generalnie, najlepiej by przedmiotowe dane pozbawić wszelkich możliwych powiązań z oryginalnymi danymi (pełna anonimizacja). Pytanie – czy jest to wykonalne?
Na pierwszy rzut oka – nie wydaje się to możliwe. Pracując na kopii danych, którą będziemy poddawali procesowi de-identyfikacji raczej pozostawimy w stanie niezmienionym wszelkie systemowe identyfikatory – klucze oraz klucze obce – odbudowanie wszelkich relacji o nie opartych wydaje się zadaniem zarówno skomplikowanym jak i wyjątkowo zasobożernym (bazy produkcyjne mają to do siebie, że zazwyczaj są duże). Może nie być to wskazane również ze względów operacyjnych – jeżeli anonimowa baza była używana do naprawy błędów – może zajść konieczność re-identyfikacji oryginalnych rekordów i ich naprawa.
Wniosek 1. W celu realizacji niektórych wymagań organizacji, aplikacja musi umożliwiać pozyskanie kopii danych poddanych jedynie procesowi de-identyfikacji. Musi być możliwość powiązania (przez osoby uprawnione, mające dostęp do oryginalnej bazy) wierszy oryginalnych i anonimowych.
Wniosek 2. Jednakże, na podstawie dowolnej analizy danych zawartych w przetworzonej kopii, bez posiadania dostępu do bazy oryginalnej, re-identyfikacja nie powinna być w żaden sposób możliwa.
Reasumując – jedynymi danymi umożliwiającymi re-identyfikację powinny zostać wewnętrzne identyfikatory z oryginalnego systemu, tj. identyfikatory nadane unikalnie przez ten system a nie pochodzące z innych systemów takie jak np. PESEL.

Continue reading Anonimizacja vs de-identyfikacja

Anonimizator – Nowy Projekt!

Cel projektu

Sytuacja wygląda tak – potrzebuję dostarczyć do zespołu deweloperskiego bazę produkcyjną aby dokonali na niej pewnych testów i optymalizacji. Występują też jeden czy dwa błędy, których nie daje się zreprodukować w środowisku testowym.

Oczywiście baza zawiera masę danych wrażliwych, które absolutnie nie powinny opuścić serwerów produkcyjnych. Zamazanie danych przypadkowymi śmieciami nie wchodzi w rachubę – rozkład statystyczny indeksów ulegnie zmianie i spora część pracy optymalizacyjnej deweloperów będzie bez sensu. Oczywistym jest, że w takim razie należy dane wrażliwe zastąpić danymi “niewrażliwymi” ale sensownymi, o w miarę naturalnym rozkładzie.

Dodatkowe wymagania

  • Dane w bazie są międzynarodowe – mają różną postać i niektóre także formaty
  • Warto zachować statystyczny rozkład danych
  • Powinna być otwarta na przyszłe formaty bazy – nowe bazy jak i rozbudowę / zmiany w istniejącej. Oraz nowe formaty danych.

Zarys rozwiązania

Swego czasu, podczas jednego z projektów, przygotowałem trochę klas generatorów danych testowych, takich jak dane osobowe, adresy, adresy e-mail. Dane bazowe dla generatorów były wyłącznie polskie a ponadto moduł adresów był potraktowany bardzo po macoszemu. Niewątpliwie jest to jakiś punkt wyjścia, ale zdecydowanie zbyt prymitywny na potrzeby funkcjonalnej anonimizacji. Głównie dlatego, że generatory generowały dane zupełnie przypadkowe (Do pewnego stopnia – np. nr PESEL i imię czy nazwisko były dostosowane do płci osoby, podobnie jak PESEL uwzględniał datę urodzenia osoby – o ile została dostarczona w przeciążonej metodzie.) a w obecnym przypadku musimy mieć możliwość kontroli nad zakresem zmian – np. rok i miesiąc urodzenia pozostają oryginalne a randomizujemy wyłącznie dzień albo losujemy imię o identycznej długości (chociaż to, może już nie spełniać wszystkich wymagań…).
Warto też by aplikacja dostarczała na tyle wygodny interfejs, by mogła z niego korzystać uprawniona osoba (Administrator Danych Osobowych), która prawie na pewno nie będzie programistą… Już na wstępie wydaje się zasadnym taki sposób przygotowania konfiguracji procesu, by rozdzielić opracowanie reguł od ich wykonania, oraz w pełni zabezpieczyć dane w bazie produkcyjnej przed niepowołanym dostępem ale także uchronić je przed celowymi lub przypadkowymi zmianami.

Literatura przedmiotu

  1. Niewątpliwie w pierwszej kolejności warto sięgnąć Ustawa o Ochronie Danych Osobowych.
  2. Ciekawym źródłem przydatnych wskazówek i wytycznych jest stosowna ustawa amerykańska dotycząca między innymi anonimizacji i deidentyfikacji pacjentów (HIPAA) wskazana na stronie Wikipedii – De-identification, i w interesującym zakresie dokładniej omówiona tutaj: Protected health information. Zamierzam dokładniej omówić ten ostatni artykuł w kolejnym poście, gdyż te wytyczne są bardzo istotne dla projektowania architektury systemu.