Beginning software architecture (for Yun)

Every programmer starts her career with something small. Implement a small function. Then implement a couple of functions talking to each other. Then implement a module, with dozens of functions, and maybe error handling and an API.

But sooner or later, we all want to move on and to step up to the higher abstraction level. We want to oversee the whole software system. We want to learn how to design it — how to do software architecture. But because this is our first time when we are stepping up one abstraction level higher, it is often very hard to do. Where can I start? When am I finished? How do I know I’ve created a right architecture?

Teachers and universities often don’t help but instead make things even worse, because they overload us with huge amount of information and detailed requirements about the architecture.

Meanwhile, there is only one thing about software architecture that is really important.

Architecting software is like caring for your child.

You want that your child will be safe and healthy; and that he will be loved, and have a long and happy life.

Safety. Your software might crash in run-time, or destroy valuable data. If it depends on its environment (other software or hardware) to run — teach your software, how to recover, when its environment fails. Teach your software, how to protect against the input from hackers and unprofessional users. Teach your software to change or produce data, only if it is fully sure it is working correctly. Teach your software, how to sacrifice one part of it to protect the whole, and teach it to run without one of its parts.

Health. Obesity is the most important problem for software. Always try to implement the same functionality with less code. Do not implement functionality, which nobody needs, but do prepare the software for the challenges it will definitely expect in the future — plan for extensibility. Use refactoring to avoid code areas that nobody is able to understand and to change, because these are the dead areas of the software body, limiting its flexibility.

Software is often created it teams. You want that the other team members love and care about the software as you do. Make sure that everyone writes code that can be read by anyone — force a uniform programming style if needed. Ensure that it is safe for team members to use the code of other team members — no unexpected results, proper error handling, consistent conventions. Avoid code ownership, because you want to get a lovely software system, and not just a set poorly interconnected moving parts.

For software to have a happy life, it must be loved and used by users. Ensure you not only understand the software requirements, but also why the users have these requirements. Work with the users to define even better requirements, which will make your software faster, slimmer or robuster. Come up with the ideas how to make your software even more lovable — a successful software will get more loving and motivating hands to work on it, while an unsuccessful software will be abandoned and die.

It is not easy to care for a child, nor it is easy to create a good software architecture. There is no rules equally suitable for all children — every time you will have to find a proper answer, may be by trial and error. But the results of the job done right might make you equally proud and your life fulfilled.

Война систем

Война в 21-м веке. Дико, нелепо, не складывается. Не верится. Ведь Интернет уже, как в свое время Кольт, уравнял всех людей — по крайней мере по доступу к информации. Ведь давно уже все, кто поуспешнее, работают в интернациональных корпорациях с отделениями по всему миру и командами, разбросанными по всему глобусу. Ведь все уже привыкли, что можно просто сесть в самолет и через несколько часов появиться в любой точке планеты, чтобы поглазеть на людей, полюбоваться красотой архитектуры и ландшафта, насладиться незнакомой пищей. Ведь многие уже настроились и ждут что вот-вот сделают наконец единое планетарное правительство, чтобы исключить всю эту никому не нужную возню с паспортами, визами, пошлинами и прочим бюрократическим хламом. Что можно будет наконец освободить значительные средства, идущие на содержание армий, и оставить только полицию.

А тут, на тебе. Один атавизм — более-менее случайно выбранный кусок планеты с границей, гербом и гимном — страна — воюет с другим таким же атавизмом. Но обе стороны сидят при этом в Фейсбуке со своих айфонов. Оксюморон. Как такое в голову укладывается?

По моему, никак. Страна в 21 веке не может воевать с другой страной за территории. Это было бы просто детским садом.

Речь может идти только о конфликте несовместимых цивилизаций.

Возьмем Израиль и Палестину. С одной стороны, евреи, которые жили там веками, которым эта территория дана непосредственно Богом по нерушимому завету и у которых все религиозно значимые события произошли именно там. С другой стороны, палестинцы, которые также жили на этой территории веками, и которых силой и нахальством вытесняют с тех самых мест, где жили, трудились и похоронены их предки. Кстати, значительная часть палестинцев — христиане. И для них эта территория тоже является тем святым местом, где родился, учил и погиб Спаситель…

В конфликте между Россией и Западом, который сейчас происходит по всему миру, а в наиболее активной фазе на Украине, наверняка тоже идет речь о столкновении цивилизаций. Есть очень много отличий между Россией и Западом, но по-моему, весь конфликт можно привести к одному коренному отличию, а именно, к вопросу о государстве.

В современной западной концепции, государство стоит не выше каждого отдельного гражданина, а успешность государства определяется в первую очередь тем, насколько успешны (счастливы, здоровы и т.п.) его граждане, каждый в отдельности. В России успешность государства определяется тем, какие великие проекты (индустриализация, поворот рек, космос) государство осуществило и насколько его боятся или уважают другие государства. При этом интересы государства стоят выше интересов каждого отдельного гражданина.

Вследствие этого, в западной концепции очень четко различаются понятия страна, народ, государство и правительство. Государство предполагается исполнителем социального заказа — оно должно на наши налоги обеспечить безопасность, дороги, энергетику, экономику и прочую инфраструктуру. Грубо говоря, оно такой же исполнитель, как продавец автомобилей или строитель вашего дома. Исполнители часто хотят наебать заказчика: работать поменьше и взять побольше. Заказчики хотят обратного. Возникает ситуация торга или противоборствия, т.е. народ торгуется с государством, и каждый хочет заплатить государству поменьше и получить побольше. Поскольку на Западе народ и государство в принципе не бывают едины, понятие “страна” может обозначать либо народ, либо государство, в зависимости от контекста.

Государству для выполнения его обязанностей положено иметь силовой аппарат, который государство могло бы применить и против народа. Чтобы исключить эту ситуацию и обеспечить равноправный торг народа с государством, приняты некоторые инструменты демократии, например сменяемость правительства и независимость средств массовой информации, которые заботятся о том, чтобы не приходилось менять шило на мыло. На Западе правительство меняется, а государство остается. Можно быть недовольным текущим правительством, но гордиться государством. Можно быть недовольным государством, но любить страну.

В России, все эти четыре понятия слиты в одно. Критикуя Путина, критикуется не только текущее правительство, но и государство в целом. Критикуя российское государство, критикуется также и страна в целом, а значит и российский народ. Поэтому Путин, похоже, совершенно искренне считает российскую оппозицию врагами России и россиян — ведь они критикуют его действия.

Когда Запад вводит санкции против текущего правительства России, то он ожидает, что российский народ поймет, что его текущим правительством в мире недовольны, и может быть задумается на следующих выборах и подправит состав правительства. А в России это воспринимается как санкции против российской государственности в целом, а значит и против страны, и против каждого россиянина в отдельности. В результате все с радостью воспринимают ответные санкции против Запада. Хотя на самом деле произошло вот что: текущее правительство натворило дел в Украине, Запад наказал наиболее злостных чиновников, которые представили это дело так, как будто всю страну наказали, а в результате пострадали все россияне.

Т.е. говоря по простому, Путин наебал россиян. Ведь Западу не понравился только Путин и его соратники, а отвечать пришлось всем россиянам. Причем он сделал это так тонко, что все даже с радостью кинулись под топор санкций.

Это ему удалось только потому, что в российской концепции принято ставить государство выше отдельных граждан. Ведь если интересы государства выше интересов граждан, то торг неуместен и состояние противоборствия между народом и государством вредно. А значит, не нужна и демократия и независимая пресса, ведь народ в данной концепции не должен иметь права быть недовольным государством. При отсутствии демократии, сменяемость правительства также не может быть обеспечена, т.е. правительство перестает быть текущим управителем дел государства на определенный срок и становится самим государством. Критика правительства таким образом является критикой государства, а раз государство важнее народа и народ живет для того, чтобы государство осуществляло свои великие проекты, то критика правительства является и действием против народа и против страны в целом.

Да, такая система позволяет эффективно осуществить много великих проектов. Пока СССР запускало человека в космос, в Бельгии люди придумывали новые сорта вафель. Проблема только в том, что при этом народ утрачивает какую-либо возможность не быть наебанным государством. Потому что а) средства массовой информации под контролем государства, народ и не поймет, где его наебывают и б) те, кто тем не менее смогут понять, не смогут этому ничего противопоставить, не только потому, что они моментально станут “агентами” и “врагами народа” и пойдут лес валить или принудительно лечиться от головы, но и потому, что они и не должны себя противопоставлять государству. Ведь даже в концепции интересы государства важнее интересов отдельных личностей, а значит государство имеет право наебывать свой народ.

По-моему, весь конфликт на Украине и состоит в том, что простые украинцы помнят, как их каждое новое правительство наебывало, но хотят хотя бы сохранить шанс, что рано или поздно они выберут себе такое правительство, которое если и будет наебывать, то по-божески. В составе России у них такого шанса не будет вообще, потому что его не существует концептуально, в принципе. В России государство ебет народ — всегда. Против того и воюют.

Auto fahren: Monat eins

Die Fahrschule bereitet dich auf das Auto fahren ungefähr genauso gut vor, wie die Uni auf die reale Arbeitsbedingungen vorbereitet. Also, unzureichend.

Jede Fahrt mit dem eigenen Auto kostet mir mehr Nerven und Kräfte als die Fahrprüfung.

Zum einen, es fehlt eine zweite, erfahrenere Person im Auto. Niemand kann bestätigen, dass ich richtig fahre, oder auf meine Fehler hinweisen. Das macht mich ziemlich unsicher.

Zum anderen muss ich jetzt während der Fahrt all das übernehmen, was in der Fahrschule der Lehrer macht: Klimaanlage einstellen, Scheiben waschen und sagen, wohin es lang geht. Das lenkt ab vom Fahren selbst, das haben wir nicht in der Schule trainiert, und deswegen macht es mich unsicher.

Was wir noch nicht trainiert haben, ist parken in den Parkhäusern. Die Theorie, wie man ein– und ausfährt und bezahlt, die kenne ich. Aber: in welchem Gang muss ich einfahren? Darf ich die Gegenfahrbahn benutzen, um steiler einzufahren? In welchem Gang fahre ich auf? Muss ich Licht einschalten? Was ist sinnvoller — vorwärts oder rückwärts einparken? Und das wichtigste: spürt man im Auto, dass man gerade ein anderes Auto oder einen Pfeiler touchiert? Ich dachte, ich hätte noch rechtzeitig anhalten können, wenn ich was höre oder spüre. Tatsächlich habe ich erst dann was gehört, wenn der Außenspiegel schon angebrochen war. Man muss immer in alle Richtungen SCHAUEN!

Ich war auch nicht auf das Gefühl vorbereitet, das man spürt, wenn das Auto kaputt geht. Einen Tag nach dem Autokauf den Spiegel beschädigen fühlte sich so an, als ob ich meinen Arm gebrochen hatte.

Wenn dann der Service von Alfa Romeo mir einen Kostenvoranschlag von über 3000 € gemacht hat (nicht nur für den Spiegel, da gab es sonst noch vieles zu tun), war das nicht mehr lustig. Gut, einige Sachen habe ich über die Gewährleistung beheben lassen, und ein Ersatzspiegel hat mich auf Ebay 40€ gekostet. Aber man lernt unglaublich viel dazu. Zum Beispiel, wie man das CD Radio mit zwei Bügeln aus der Schacht herauszieht.

Das sonstige Thema, wo ich durch die Fahrschule nicht vorbereitet war, ist das Zubehör. An einen neuen Vebandskasten und die Warnweste habe ich noch gedacht. Was ich sonst noch mitfahre ist eine kompakte Lampe, ein Glasreinigungsmittel, eine Waschlappe,  ein KFZ-Ladeadapter, eine Parkuhr und Wasserflaschen. Ich habe das Gefühl, dass ich noch weitere Sachen mitfahren sollte, weiß aber nicht, welche.

Was ich auch nicht wusste, was genau würde mein Fahrzeug verkehrsuntauglich machen. Wenn z.B. die Sonnenblende und die Scheibenwischer nicht gehen, darf ich das Auto trotzdem fahren? Das hat mich noch zusätzlich verunsichert, abgesehen von den üblichen Schwierigkeiten (ein Benziner statt Diesel, andere Maßen, größerer Wendekreis).

Traurig fand ich die Tatsache, dass der Weg zur Arbeit über die Autobahn (24km und 29 Minuten) weniger Benzin verbraucht als der Weg über die Landstraße (17km und 37 Minuten). Die Alfa verbraucht bei 20kmh doppelt so viel als bei 80kmh. Wohl das technische Problem von allen Verbrennungsmotoren. Soll mein nächstes Auto elektrisch sein?

Spätestens nach einer 1,5stündiger Autobahnfahrt habe ich auch festgestellt, dass die einfachen Regeln meines Fahrlehrers, wie man den Sitz einstellt, nicht ausreichend sind. Einen Nackenkissen habe ich schon bestellt, und probiere gerade unterschiedliche Rückenneigungen aus. Abgesehen davon wundert es mich, dass ich in meiner Sitzposition manchmal den Ampel nicht sehen kann.

Was ich aber sehr gut sehen kann sind die Schnauzen von Autos hinter mir, die zu oft an meinem Heck kleben. Verstehe ich nicht. Das passiert entweder dann, wenn ich genau die angezeigte Höchstgeschwindigkeit + 9kmh fahre. Dann werde ich auch nicht schneller fahren und mein Fahrerlaubnis riskieren. Oder passiert es dann, wenn ich mich gerade verlangsame, um in den Parkhaus richtig einzufahren. Dann werde ich auch nicht schneller sein. Und genau das macht mich fertig, denn ich hasse es, wenn ich jemandem im Weg stehe, hier kann ich mich aber nicht anders verhalten.

Ach ja, den Aufkleber “Anfänger” habe ich entschieden nicht anzubringen, weil er die Ästhetik von Alfa stören würde. Trotzdem gibt es erstaunlich wenig Leute, die hupen oder abgesehen vom Drängeln sonst sich arschig verhalten würden.

Ansonsten lernt man unerwartet viele Kleinigkeiten dazu. Dass z.B. der Fahrzeugschein nicht in die Geldbörse passt und eine neue muss her. Dass die Kennzeichen nicht gleich sind und eins davon muss hinten sein. Dass die meisten europäischen Autos die Tankklappe rechts haben, und die asiatischen links. Dass der Ölstand beim warmen Motor überprüft werden muss, während alle anderen Flüssigkeiten beim kalten Motor zu prüfen sind. Dass Hemde mit einer Brusttasche praktischer ist, als die Hemde ohne, weil dann der Parkticket in der Haste mit dem Mund gehalten werden muss.

Fazit: es gibt noch ganz viel zu lernen und ich verstehe nicht, warum ich dabei nicht unterstützt werde. Ich finde keine sinnvollen Bücher oder Kurse für Fahranfänger. Als ob niemand bisher diesen Weg gegangen ist, oder als ob die gewonnene Erfahrungen es nicht Wert sind, geteilt zu werden…

Being a happy bricklayer

“What are you doing?“
“I’m laying bricks,” said the first bricklayer.
“Feeding my family,” said the second bricklayer.
“I’m building a cathedral,” said the third bricklayer.

When I’ve learned this story in the primary school, I was shocked to see how shitty the life of the first two bricklayers were. The first one didn’t even had any intrinsic motivation to do his job, so he was probably a slave, a prisoner or some other kind of forced workforce. And the financial situation of the second one was apparently so critical that he was forced to take a job — any job he could find — to feed his family, even though he wasn’t really interested in laying bricks or perhaps even in construction works altogether.

I’m very happy to say that I was building a cathedral on every job I took so far. And frankly speaking, I don’t even see a point to do it differently. A job takes 8 hours a day. And for a hobby we could find, perhaps, one hour per day, on average? So by making your job to your hobby, and your hobby to your job, you increase the happy time of your life by 700%.

Another shocking aspect of that story is the missing loyalty of the first two workers. Per my upbringing and education, I’m normally very loyal to my employer, at least as long as they are loyal to myself. When my employer decides to hire me, they have some purpose in mind. It is the question of my loyalty, and of my integrity, to deliver upon it. But the first two workers seemed to be absolutely ignorant to their purpose in their organization!

That’s why I don’t really know what to say, every time when I hear someone declaring that his/her purpose in the company is not related to money. I mean, common, private companies have exactly one primary goal, one reason to exist: to earn money. Yes, they might have some cool vision like not being evil, or having a laser-sharp focus on perfect products, but these goals are all secondary. They are quickly forgotten when the primary goal is in danger. No company can survive for long, unless it follows the primary goal.

Therefore, I do really think that the purpose of all and every employee should be to see how s/he can help the company to earn or to save money. If s/he is not okay with that, well, wouldn’t s/he be much more happier working in a government agency, a non-government, a scientific, military, or a welfare organization?.. Just asking…

Tolles UX

HUK24.de hat eine faszinierende (und teilweise mutige) UX. Probiert mal selber aus! Was mir gefallen hat:

1) Sie verkaufen die KFZ-Versicherung in exakt gleicher Art und Weise, wie ich es kaufen will. Es gibt keine Landing Pages mit glücklichen Menschen, die mir die Vorteile erklären. Es gibt keine Testimonials. Es gibt keine übergroße CTAs “Jetzt kaufen”. Stattdessen verstehen sie, dass wenn ich zum ersten Mal auf huk24.de komme, bin ich noch am Vergleichen, welches Versicherungsunternehmen ich auswähle, und deswegen geben sie mir exakt das, was ich möchte: schnell, unverbindlich und unkompliziert mal berechnen zu können, wie viel ich in meinem Fall zahlen müsste.

2) Aber das noch nicht alles. Am Ende der Kalkulation gibt es naturlich einen CTA “Jetzt abschließen”. Wenn ich aber an dieser Stelle den Tab verlasse und mir ein Paar Tage Zeit nehme, um die anderen Alternativen abzuklappen, und dann zurückkehre, wirft mir die Seite keine “Session ist abgelaufen”, sondern sie weißt noch alles, was ich damals eingetragen habe, und ist immer noch bereit, sofort einen Vertrag abzuschließen! Das allein ist goldig.

3) Wenn ich dann bei der Bestellung an den Punkt komme, wo Zugangsdaten vergeben werden, fragen sie nur noch nach einem geheimen Passwort. Die Benutzerkennung wird dann automatisch generiert und mir angezeigt, so dass ich meine komplette Zugangsdaten in meinem KeePass abspeichern kann. Und wenn ich mich nicht täusche, wird die E-Mail erst später abgefragt, und zwar an der Stelle, wo ich selber daran Interesse habe, sie mitzuteilen (z.B. damit ich meinen Versicherungcode erhalten kann).

4) Es ist möglich, bei der Bestellung eine WerberID einzugeben, wenn ein anderer Kunde von HUK24 sie mir empfohlen hat. Es gibt aber auch einen Hinweis, dass ich die WerberID auch später (sogar nach Vertragsabschluß) eintragen kann, falls ich sie nicht zur Hand habe.

5) Wenn ich die Seite in einem eingeloggten Zustand verlasse und später einfach www.huk24.de eingebe, bekomme ich nicht die Startseite zu sehen, sondern ein Hinweis, dass ich automatisch ausgeloggt wurde und mich wieder einloggen kann. Ich kann zwar trozdem nicht-eingeloggt weiter surfen, aber es besteht schon ein softer Zwang, mich einzuloggen. So kann HUK24 mich besser verstehen und mir personalisierte Funktionen anbieten.

6) Nach der Anmeldung komme ich zum “Meine HUK24” Bereich, wo in der Mitte die exakt 6 wichtigsten Funktionen abgebildet sind, die ich überhaupt jemals brauchen könnte: huk247) Und viele kleinere UX-Merkmale, die ich toll finde, z.B. durchgehend werden Buttons nicht deaktiviert, sondern beim Klicken erhält man eine Overlay mit Erklärung, was man noch machen müsste, usw.

Mal schauen. Wenn ihr eigentliches Produkt (die Versicherung) genau so gut funktioniert wie die Webseite, habe ich eine richtige Entscheidung getroffen.

Enterprise Innovation

Well, my Enterprise Seasons model was too simple. Actually, after creating their first successful “flywheel” product, some corporations proceed with creating second, third and further successful products, always remaining an innovative enterprise, at least at some of its parts. There are a lot of advantages in this:

- Risk diversification. If one product fails for whatever reason, another products will keep the company afloat.

- The law of diminished returns can be worked around. Instead of investing more and more creative power into smaller and smaller uplifts, one can enjoy a much higher ROI with a new fresh product.

- Linear scalability. Growing the company by growing production and sales of a single product involves a lot of work with people, processes, and inevitable bureaucracy. Growing the company by creating a new product, can be just copying of its existing structure.

- Several revenue sources can allow for aggressive market policies, so that the company might allow one of its products to be intentionally unprofitable, to gain market share.

- At last, there might be synergy between different products, for example ideas or methods from one product can be applied to another, or selling a combination of products might be easier.

Therefore, for me it is even more interesting to understand, why there are so many enterprises that have problems with innovations. Why some enterprises don’t keep creating more and more products? So far, I’ve seen the following scenarios:

- Cultural incompatibility. Discovering a new product is everything but safe: 90% of new products fail. The traditional 19-century world view of a safe, life-time workplace, and a state welfare system eliminate the necessity of innovation. “We will work in the same safe market niche, and hopefully it will last until we leave the job and have our rent, and if not, the welfare system will help us to remain afloat and to find a new job.”

- Ethical reasons. Growing a company can be seen as a consumeristic, anti-ecological activity. In this case, the company not only doesn’t create new products, also continuous development of its primary product is almost non-existing; it is in maintenance mode.

- While investing most of resources into establishing and developing its secondary product, the company’s primary product is hit and almost destroyed by a sudden market shift; its development is frozen and everyone keep working to make the secondary product the new primary.

- Even though the primary product is running well, most of its revenues are paid out to foreign shareholders running a short-time strategy. Innovation is barely possible, because there are not enough people and money for it.

If some innovation is nevertheless trying to happen, often there are cultural difficulties:

- The Sun and stars fallacy. Sun is so much brighter than stars that we don’t see stars at day. The scale of the primary product is much higher than the one of a new product; it always has more visitors, page views, registrations, orders, revenue and operational spendings. “What? Your new product only generates X orders per month? What a fail, our primary product generates YYYYY orders! Let’s spend more on the primary product!” The trick is, if you don’t invest into the new product to grow it, it will also never reach maturity. The primary product was also so small in its initial stages.

- The No-Fail mentality. When searching for a new product, everyone in the team (PM, designers, developers) must have the “Fail Fast, Fail Cheap” mentality. On contrary, developing a mature product, the team must have a “No Fails Allowed” principle. If you like test-driven development, run-time performance optimization, software security, writing source code commented and formatted to style guide, creating comfortable in-house frameworks and planning several sprints ahead, you should develop a mature product. But, if you like fast user feedback, discussions about usability and the minimal viable product, several releases each week, and your software works only in 80% of cases, your source code is dirty as devil, but you’d rather spend more time discussing one-pixel changes in the UI, then you should be in team discovering a new feature or product. When companies ignore these differences and assign their “No-Fail” developers to discover a new product, this only leads to everyone’s frustration.

- The additive development fallacy. Development of the primary product is often additive. Projects like “We expect X% more users, have to scale hard– and software”, “We need feature X due to law changes”, or “we need a more modern design, let’s do a relaunch”, when implemented, usually never need to be rolled back. The problems begin, when new products or features are also implemented in the additive manner. Instead of starting with hypothesis verification and then a prototype, a complete product or feature is conceived, designed and implemented. Several months later, it rolls out, gets some less-than-moderate user attention, and starts to rot quietly in its tiny dark corner. Nobody has the balls to sun-set this feature, because, well, the company’s culture is additive, and the months of development are perceived as an asset. In reality, such features are a debt, constantly sucking team efforts and energy for maintenance, support, porting, translation, and operating.

I’m not sure yet, how enterprises create a new successful product. When observing enterprises with several products, I have the feeling that either

- a charismatic leader builds his very own small empire and creates a new product as a by-product (no pun intended),

- or the merge and acquisitions department grabs a product together with its team, and successfully integrates it into the company,

- or the company organizes its own startup incubator. The company owns then only partially its new products, and a lot of the existing infrastructure is not re-used, but at least the cultural issues are solved,

- or, in 0,00001% of cases, companies such as Valve have an innovation culture from the very beginning on.

Please share your experiences of innovations within an enterprise.

CSU

Aus gegebenem Anlass frage ich mich, wie lange es dauern wird, bis CSU endgültig das öffentliche Image so wie bei NPD erreicht und ein Verbotsversuch gestartet werden könnte.

Ich kenne mich in der Politik ganz schlecht aus. CSU habe ich zum ersten Mal kennengelernt, als Herr Steuber über seine christliche Leitkultur gesprochen hat. Ich habe zwar meinen persönlichen Weg zum Christ gefunden, und würde auch jedem anderen Mensch herzlichst wünschen, den Zugang zum Christ zu finden. Allerdings bin ich dagegen, wenn man es aufzwingt. Der liebe Gott hat es allem Anschein nach jedem Menschen frei gelassen, und das soll auch so bleiben.

Außerdem gibt es auch ganz viele Deutschen, die keine Christen sind: will Herr Steuber sie auch aus dem Land schicken? Und nicht zuletzt, bei allen positiven Aspekten von Christentum darf man nicht vergessen, dass mit der christlichen Religion auch ganz viel Leiden, Aberglaube und Jahrhunderte von Kriegen verbunden sind.

Wir leben in einer humanistischen und demokratischen Kultur, und diese soll auch die Leitkultur für die Neuankömmlinge werden. Die Religion hat hingegen in der Politik nichts zu suchen.

Nun kriege ich von CSU wieder so einen Hals, wenn ich die Aussagen höre, wer (sprich die Zuwanderer) noch nicht eingezahlt habe, solle auch nichts ausgezahlt bekommen. Nach dieser Logik sollten wir dann ja auch ganz viele Deutschen aus Harz IV rausschmeißen, die auch niemals gearbeitet haben. Sonst wäre das ja eine Diskriminierung nach Nationalität. Das wäre aber nur die halbe Miete; es gibt doch ganz viele Menschen, die Harz IV bekommen, ohne jemals gearbeitet zu haben — das sind Jugendliche, die noch in der Schule sind, oder nach der Schule noch keine bezahlte Arbeit bekommen haben. Ausgerechnet für diese Zielgruppe hat doch das solidarische soziale Netz in Deutschland ihre größte Bedeutung und Wirkung. Sollen wir sie dann auch rausschmeißen?

Das Problem mit der Zuwanderung kann man aber auch aus einem anderen Blickwinkel betrachten. Ich wäre z.B. nicht nach Deutschland gekommen, wenn meine Eltern in Deutschland keine Unterstützung vom Staat bekommen hätten. Ich wäre dann entweder in Russland geblieben, oder in die USA gegangen, wo ich nicht nur zwei– bis dreifaches mehr verdient hätte, sondern auch die Chance hätte, mit den ganz großen der Zunft zusammen zu arbeiten.

Dieselbe CSU redet davon, dass der Zuzug von hochqualifizierten Menschen erleichtert werden muss. Doch sie geht von einer Wahnvorstellung aus, dass Deutschland nur seine Pforten öffnen müsste, und schön wäre ein Strom der hochqualifizierten da. Da täuschen sie sich bitter. Deutschland ist längst nicht das attraktivste Zuzugsland, zumindest nicht in jedem Beruf. Was die Software-Branche angeht, hat Deutschland nur sehr wenige weltweit erfolgreiche Projekte vorzuweisen, und sieht dementsprechend eher provinziell aus, so dass die wirklich hochbegabten hier für sich keine Verwendung finden würden.

Ich habe Deutschland unter anderem deswegen vor USA gewählt, weil es mir wichtig ist, meine Eltern regelmäßig sehen zu können. Die Zuwanderungspolitik Deutschlands muss als Frage der Familienzuwanderung gesehen werden. Wenn ich grob überschlage, habe ich und meine Eltern an Steuern das doppelte davon gezahlt, was ich und meine Eltern von dem Staat erhalten haben. Abgesehen davon setzen wir unsere Arbeit für die Entwicklung von hochmodernen Geräten und Software ein, so dass die deutsche Wirtschaft wettbewerbsfähiger wird. Und wir geben das Verdiente in Deutschland aus, weil wir nicht das Geld zurück in die Heimat schicken müssen. Deutschland hat also für unseren Zuzug schon etwas bezahlt, das kam aber verhältnismäßig preiswert.

Das alles ist bestimmt kein Geheimnis und die seriösen Politiker, die sich mit der Zuwanderung professionell auseinandersetzen, dürften das alles schon lange wissen. Warum CSU trotzdem auf dieser braunen Karte reiten möchte, entzieht sich meinem Verständnis. Sie sehen sich doch als eine Partei der Mehrheit. Ich kann aber nicht glauben, dass in Bayern die Mehrheit so braun ist, wie die CSU es sich erlaubt.

My Decision Theory

On my way to work I usually take a bus. Once, I’ve arrived to the bus stop a little bit late and had to wait for the next bus. I looked at the timetable and found out that the next bus was going to come in 12 minutes. I take two bus stops, which takes 4 minutes with the bus, or 20 minutes to walk.

I’ve decided to walk.

Now, mathematically, it was a wrong decision. Waiting for 12 minutes, then driving with the bus 4 minutes gives 16 minutes, which is shorter than 20 minutes. But, that day was very cold, so I’ve figured out I’d better walk and warm me up than staying at the bus stop for 12 minutes, possibly catching a cold. So, even if the decision was mathematically wrong, it was correct from the health point of view.

Several minutes into walking, I’ve watched a bus driving past me. What I’ve forgot while making my decision, is that two different bus lines pass my bus stop, and I can take both to come to work. I’ve looked up just one timetable and forgot about the second one.

As a consequence of this decision, I came into work several minutes later than I ought to come. Normally, this is not a very good thing. But I’ve worked a little bit more on the previous day, and I didn’t have any meetings scheduled, so that this hasn’t caused any major troubles. On the positive side, I’ve walked for 20 minutes, which was better for my health.

So, I took a decision, which was wrong both mathematically (16 minutes is less than 20) and logically (there was another bus line), but it didn’t have any major negative consequences, and indeed it was even good for my health.

Crazy, but this is how the world is. We take wrong decisions, but earn only positive consequences. Sometimes, we take perfectly correct and elegant decisions, that become huge source of negative consequences.

I’m still trying to understand how to handle it.

And this is by the way why I’m always laughing when I hear CS academics speaking about “reasoning about your code” and “formal proof of correctness”. They seem to be thinking, the biggest problem of software industry was to figure out, if 16 is less than 20.

Childhood remembered

One of the things done right in the Russian school system is the vacations schedule. The summer vacations are the largest and cover the whole summer; they start in the beginning of June, and end on August 31st. This is almost three months of the best weather in the year. For children it is so long that they feel like eternity, and the most exiting part of them are the first several days. This unforgettable feeling that you finally don’t have to do anything what you don’t want to. These summertime streets and places that belong almost completely to children, because adults are at work. This anticipation of a journey, maybe for a couple of weeks, together with the parents. And the best of it, this feeling that this joy will (almost) never end.

In 2010, Ринат Тимеркаев has made an animated movie about his home city, which is a neighbour city to the city where I was born. The city nature, architecture and overall feeling is very similar and reminds me of my home city, during the Summer vacations. The movie is called “I love you”, and its meant to be “I love you, my home city”. I didn’t quite feel it was a good fit. This year, somebody has mixed the song “Childhood remembered” by Kevin Kern with the movie, and suddenly, it made click for me. Now this is a perfect movie to remember about my summer vacations.

Four Weeks of Bugfixing

The hardest bug I’ve ever fixed in my life took me 4 weeks to find. The bug report itself was pretty simple, but I have to give more context first.

I was one of the developers of a Smart TV software, and the bug related to the part of the software responsible for playing video files stored on your USB memory or drive. The CPU that was available for this task was a 750MHz ARM chip, and clearly it had not enough power to decode video (let alone HD video) in software. Luckily, every digital TV set has a hardware H.264 decoder, and our SOC was so flexible that we could use it programmatically. In this way, we were able to support H.264 video playback (too bad for you DivX and VC-1 owners).

Technically, the SOC has provided a number of building blocks, including a TS demux, an audio decoder, a video decoder, a scaler and multi-layer display device, and a DMA controller to transfer all the data between the blocks. Some of the blocks were present more than once (for example, for the PIP feature you naturally need two video decoders) and therefore could be dynamically and freely interconnected programmatically, building a hardware-based video processing pipeline. Theoretically, one could configure the pipeline by writing some proper bits and bytes in specified configuration registers of the corresponding devices. Practically, the chip manufacturer has provided an SDK for this chip, so that you only had to call a pretty well-designed set of C functions. The SDK was intended to run in the kernel mode of a Linux kernel, and it came from the manufacturer together with all building scripts needed to build the kernel.

Furthermore, this SDK was wrapped and extended by some more kernel-side code, first to avoid dependency on a particular SOC, and second to provide some devices to the user-mode, where the rest of the Smart TV software was running. So to play video programmatically, one needed to open a particular device from user mode as a file, and write into it a TS stream containing video and audio data.

Sadly, there are many people out there who have invented a lot of different container formats besides of TS. Therefore, our software had to detect the container format of the file to be played, demux the elementary streams out of it, then mux them again into a TS stream, and then hand it over to the kernel mode code. The kernel code would pass the TS bytes to the DMA device, that would feed the hardware TS demuxer, that would send the video elementary stream to the hardware video decoder, where it finally would be decoded and displayed.

For the user mode, we could implement all possible container formats ourselves (and this would mean some job security for the next 10 years of so). Fortunately the Smart TV software was architected very well so that the GStreamer framework was used (for you Windows developers it is an open-source alternative to DirectShow). The framework is written in C (to be quick) and GLib (to be object-oriented) and provides a pipeline container, where you can put some filters and interconnect them. Some filters read the data (sources), some process the data (eg. mux or demux), some use the data (sinks). When the pipeline starts playing, the filters agree on which one will drive the pipeline, and the driver would pull the data from all filters before it in the pipeline, and push the data into all the filters after it in the pipeline. Our typical pipeline looked like this (in a simplified form): “filesrc ! qtdemux ! mpegtsmux ! our_sink”. As you can expect from such a framework, there are also a lot of stuff related to events and state machines, as well as memory management.

So now, back to the bug report. It looked like this: when playing a TS file from USB memory, you can seek forward and backward with no limitation. When playing any other container format, you can seek forward, but you cannot seek backward. When seeking backward, the video freezes for several seconds, and then the playback continues from the latest position.

This is the sort of bugs when I think this might be fixed in a day or two. I mean, it works with TS, it doesn’t work with MP4, it is fully reproducible, so just find out what is different in those two cases and you’ve caught it.

The GStreamer pipeline in TS case looked like this: “filesrc ! our_sink”. So it must be either qtdemux or mpegtsmux. I’ve built another MP4 demuxer and replaced qtdemux with it. Negative, the bug is still there. No wonder, it also appeared in other container formats. I couldn’t replace mpegtsmux, because I haven’t found any alternatives. So the only thing I could do is to use the pipeline “filesrc ! qtdemux ! mpegtsmux ! filesink”, write the output into a file, and then try to dump the TS format structure and to look for irregularities.

If you know TS format, then for sure, you are already very sympathetic with me. TS is a very wicked and complicated format, and they repeat some meta-information every 188 bytes, so that the dump of several seconds of video took megabytes. After reading it, I didn’t find anything suspicious. Then I’ve converted my test MP4 video into a TS using some tool, dumped that TS, and compared. Well, there were some differences, in particular, how often the PCR was transmitted. Theoretically, PCR is just a system clock and should not influence the playback at all, but practically we already knew about some hardware bugs in the decoder making it allergic to unclear PCR signaling. I’ve spent some time trying to improve PCR, but this didn’t help either.

I have then played the dumped TS file, and I could see the seek backwards that I did during the recording. This has convinced me that mpegtsmux was also bug-free. The last filter I could suspect was our own sink. Implementing a GStreamer filter is not easy to do right in the first time. So that I went through all the functions, all the states, all the events, informed myself how the proper implementation should looked like, and found a lot of issues. Besides of a lot of memory leaks, we’ve generated a garbage during the seek. Specifically, GStreamer needs it to work in the following way:

1. The seek command arrives at the pipeline and a flush event is sent to all filters.

2. All filters are required to drop all buffered information to prepare themselves for the new data streamed from the new location.

3. When all filters have signaled to be flushed, the pipeline informs the pipeline driver to change playback location.

4. After the seek, the new bytes start flowing in the pipeline. Our code has conformed to this procedure somewhat, but did the cleanup prematurely, so that after the cleanup some more stale data polluted our buffers, before the data from the new location arrived.

I couldn’t explain why did it work with TS but not with MP4, but I’ve figured out that fixing it will make our product better anyways, so I’ve fixed it. As you can imagine, this didn’t solve the original problem.

At this point I’ve realized that I had to go into the kernel. This was a sad prospect, because every time I’ve changed anything in kernel, I had to rebuild it, then put the update on a USB stick, insert it into TV set, upgrade it to the new kernel by flashing the internal SOC memory, and then reboot the chip. And sometimes I’ve broken the build process, and the new kernel wouldn’t even boot, and I had to rescue the chip. But I had no other choice: I was out of ideas what else I could do in the user space, and I suspected that in the kernel space, we also had a similar issue with a garbage during the seek.

So that I’ve bravely read the implementation of the sink device and changed it in a way that it would explicitly receive a flush signal from the user space, then flush the internal buffer of the Linux device, then signal back to user space it is ready, and only then I would unlock the GStreamer pipeline and allow it to perform the seek and start streaming from the new location.

It didn’t help.

I went further and flushed the DMA device too. It didn’t help. Also flushing the video decoder device didn’t help.

At this point I’ve started to experiment with the flush order. If I first flush the DMA, the video decoder might starve in absence of data and therefore get stuck. But if I flush the decoder first, the DMA would immediately feed it with some more stale data. So perhaps I have to disconnect the DMA from video decoder first, then flush the decoder, then the DMA, and then reconnect them back? Implemented that. Nope, it didn’t work.

Well, perhaps the video decoder is allergic to asynchronous flushes? I’ve implemented some code that has waited until the video decoder reported that it has just finished the video frame, and then flushed it. Nope, this wasn’t it.

In the next step, I have subscribed to all hardware events of all devices and dumped them. Well, that were another megabytes of logs to read. And it didn’t help, that the video playback was a very fragile process per se. Even when playing some video, that looked perfectly well on the screen, the decoder and the TS demux would routinely complain of being out of sync, or losing it, or being unable to decode a frame.

After some time of trying to see a pattern, the only thing I could tell is that after the seek forward, the video decoder would complain for some frames, but eventually recover and start producing valid video frames. After a seek backward, the video decoder has never recovered. Hmm, can it be something with the H.264 stream itself that prevented the decoder to work?

Usually, one doesn’t think about elementary streams in terms of a format. They are just BLOBs containing the picture, somehow. But of course, they have some internal format, and this structure is normally only dealt with by authors of encoders and decoders. I went back to GStreamer and looked up, file by file, all the filters from the pipeline producing the bug. Finally, I’ve found out that mpegtsmux has a file having “h264” in its name, and this has immediately ringed alarm in my head. Because well, TS is one abstraction level higher than H.264, why the hell mpegtsmux has to know about the existence of H.264?

It turned out, H.264 bitstream has in its internal structure so-called SPS/PPS, the sequence parameter set that is basically a configuration for the video decoder. Without the proper configuration, it cannot decode video. In most container formats, this configuration is stored once somewhere in the header. The decoder normally reads the parameters once before the playback start, and uses them to configure itself. Not so in TS. The nature of TS format is so that it is not a file format, it is a streaming format. It has been designed in the way that you can start playing from any position in the stream. This means that all important information has to be repeated every now and then. This means, when H.264 stream gets packed into the TS format, the SPS/PPS data also has to be regularly repeated.

This is piece of code responsible for this repeating: http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/gst/mpegtsmux/mpegtsmux_h264.c?h=0.11#n232 As you can see, during the normal playback, it would insert the contents of h264_data->cached_es every SPS_PPS_PERIOD seconds. This works perfectly well until you seek. But look how the diff is calculated in the line 234, and how the last_resync_ts is stored in line 241. The GST_BUFFER_TIMESTAMP is as you can imagine the timestamp of the current video sample passing through the tsmux. When we seek backwards, the next time we come into this function, the GST_BUFFER_TIMESTAMP will be much less than last_resync_ts, so the diff will be negative, and thus the SPS/PPS data won’t be repeatedly sent, until we reach the original playback time before the seek.

To fix the bug, one can either use the system time instead of playback time, or reset last_resync_ts during the flush event. Both would be just a one line change in the code.

Now, the careful reader might ask, why could the TS file I’ve recorded using mpegtsmux in the beginning of this adventure be played? The answer is simple. In the beginning of this file (i.e. before I’ve seek), there are H.264 data with repeated SPS/PPS. At some point (when I’ve seek during the recoding), the SPS/PPS stop being sent, and then some seconds later appear again. Because these SPS/PPS data are the same for the whole file, already the first instance of them configures the video decoder properly. On the other hard, during the actual seek of MP4 playback, the video decoder is being flushed, and therefore the SPS/PPS data is being also flushed, and this is the point when the video decoder relies on repeated SPS/PPS in the TS stream to recover, and this is exactly the point when they stop coming from the mpegtsmux.

Four weeks of search. 8 hours a day, 5 days a week. Tons of information read and understood. Dozens of other smaller bugs fixed on the way. Just to find out a single buggy line of code out of 50 millions lines of code in the source folder. A large haystack would contain to my estimate 40 to 80 millions of single hays, making this bug fixing adventure literally equivalent of finding a needle in a haystack.

Categories

Recent Tweets

  • New blog post: How to merge, 3/3 http://t.co/gFjDEJVs 2 years ago
  • Oh boy, how quick time goes by. Do you recognize that puppy toy language of 90ies in this young dynamic professional http://t.co/J4k53xn4 2 years ago
  • New blog post: How to merge, 2/3 http://t.co/wXIUAEZZ 2 years ago
  • New blog post: How to merge, 1/3 http://t.co/1lOQUp56 2 years ago
  • Just posted a photo http://t.co/pCUA758O 2 years ago

Follow Me on Twitter

Powered by Twitter Tools

Archive