0 comment

Management problems and how to avoid them

The last days I listened to some episodes of a german management podcast. They discussed some common management problems or mistakes and how to avoid them. This got me thinking about my own experiences and this post is a combination of ideas from the podcast and my own thoughts. And it certainly is by no means complete or authoritative.


One of the most demotivating habits is not only to set a goal but also explicitly to define how to reach it. If you are at every stage of a project informed about every detail and progress of every task, if you always work on the important tasks yourself, if you think you know more than your coworkers and can do better, if you are able to jump in with any task at hand you probably are micromanaging your team. This is demotivating since you express a lack of trust. Try to delegate tasks. Have confidence in your coworkers because without they don’t have either. Sometimes the line between giving enough information to work on a task and giving too much information so the task can be done without thinking about is a fine one. Especially founders often never learned to delegate by specifying a task at hand as detailed as needed but not more. When the results don’t match their expectations they feel confirmed in their distrust.
Additionally don’t request status information each and every day. This holds true for management, but does certainly not apply to agile processes. So what is the difference between a manager requesting to be updated every day and a daily standup, you may ask. Well the standup is the spreading of information you as a reporting team member think is noteworthy for all (!) other team members. Reporting to your manager socio-dynamically is a totally different process. There is an imbalance in power right from the setting. The (im)balance of power in conversations in general is a topic worth its own post.

The undercover expert

This is a special type of micromanager. All by themselves they think that they can accomplish the technical problems better than anybody else because there is nothing they love as much as fiddling with details and technology. The result is that they work in their company not on their company. And since they are the A-Team, made of Chuck Norris and MacGyver in one person, their idea of management is to control everything. But they will think of this as support for their coworkers. Such a manager also will never give up control, even if they try. This is because stepping out of the way because they trusts someone else to do the job is not part of their worldview.


To pay too much is bad, but to pay poor is even worse. So don’t pay less than average. In fact if you like to get excellent work pay more than average. Money is not everything but money can be a form of appreciation. Or rather paying poor wages is a sign of lack of appreciation. If you now say that you cannot afford to pay competitive wages then you perhaps should not hire additional employees. This sounds sharp but if your revenue is so bad that you need to cut on the wages maybe your business model or way to manage is not optimal. The laws of economy say that you can not expect to buy an excess of any good by paying poor. If you pay poor for any deliverable you have to add for the risk to do so. If you take that into account you have a bit more margin to pay.
And while we’re at it: don’t work with a bonus system. Bonuses have shown to be counterproductive to create engagement with a company or job position. Most people will do anything to comply to the results defined in their agreement on objectives. This includes taking shortcuts that in the short term work to reach a goal but might harm your company if it is not the intended way to reach the goal.


Be authentic. Don’t try. Be it. If you commit to deliver something do so. If you give deadlines or goals, be specific. „Somewhere around March“ is not a date. “Monday, the 25 March at 10am“ is a date. If you define dates or deadlines, take a note and write a mail so everyone knows and can keep track. If you give positive feedback, do so in public, if you have to express criticism, do it in a one-on-one. Meetings with two or more managers and one employee are not feedback but a jury. Avoid this setting in any case. You remember my remark on imbalance of power from above?


While we are at one-on-ones: it’s typical german management style to have exactly one annual personnel talk. This meeting is thought to contain feedback, objectives, personal growth (if this is a topic at all) and salary. That’s a lot of stuff that should not be combined and once a year is too infrequent. There are two main reasons why managers avoid one-on-ones.
First they might think they have not enough time for every coworker to meet once a week or biweekly. This signals „you are not important to me“. And let’s just do some math. The typical management span in a tech company is somewhere up to 10 team members. 10 conversations of half an hour make 5 hours. Every two weeks which has 80 hours if your full time week has 40 hours. That’s not very much for one of your core tasks.
Or they are afraid of the talk. Being afraid to talk to colleagues may have one of two reasons. One is you might be afraid of what you will hear. The other is that you just don’t like to communicate so much at all. If one of those applies to you you might want to think about your job choice. There is a swabian proverb: „Not beaten is praised enough“. Don’t live by that. It never has been true.

Photo by Freepik

0 comment

Why I don’t like hackathons

Disclaimer: I never took part in a hackathon for the reasons I explain here. So all views are deduced from observing those events and their outcome.


Under which conditions would you say a software project goes bad? Let me gather some I really dislike:

  • We’re in a hurry i.e. we are short in time
  • We are actually so short in time that we can’t complete each and every task
  • We don’t have a good set of requirements
  • Outputting something counts more than doing it right (“quick and dirty is better than nothing”)
  • We have so much work to do that we ignore our health condition (at least for some “sprint time”)

Nearly every condition I mentioned above can be found in a hackathon. Because it is a challenge. Work fast, achieve most. And who attends a hackathon? Young people. Developers starting their career in tech.

What do they learn in a hackathon? Work fast, complete as many tasks as possible. Doing it quick and dirty is perfectly OK. If you don’t have a specification for a task, guess whatever you think will work and implement that. It’s OK to sit 3 days (and I mean DAYS including the nights) in a room and hack right away, ignoring how your body feels.

NO. Just fucking no.

I don’t want people to learn that quick and dirty is the standard way to do things! I don’t want them to learn that scarcity in manpower, time and quality is perfectly acceptable!

To be clear: in every project I worked there are phases when time is short and we needed to do something quick and dirty. But I always try to implement things the best way I can.

“We need people who can fix things quickly!”

Training people to quick and dirty as a standard might be exactly what the organizers aim at. I prefer my coworkers to learn to do things first right and then fast. And to find shortcuts where needed.

0 comment

WoC: Detect non-iterable objects in foreach time to time we use iterable objects, arrays, objects implementing the \Traversable interface (which iterators also do).

In the old days, real programmers didn’t check for data types, they set sort of canary flags like this:

This implements some sort of foreach {…} else {…} construct that PHP doesn’t have. Sure, it works. If you don’t turn on warnings, because if you do, you will be overwhelmed by warnings about foreach trying to act on a non-array/iterable object.

There is a solution: test your data type before running into the foreach! Yes, this means if you can not be 100% sure what sort of object you get, you have to enclose each and every foreach with an if construct. Since PHP 7.1 this block can make use of the is_iterable() function, which returns true, if the given parameter is any kind of iterable object:

For me this looks much better. The result is the same, but without warnings and the purpose is directly intelligible. The former example needs some thinking about the wtf factor of the code.

For PHP versions below 7.1 you can use some sort of polyfill function:

Thanks to the commentators of the PHP manual for this hint.

0 comment

Same procedure as last year: switch dates for daylight savings time in PHP

The same procedure every year: part of the world switches to daylight savings time (DST). Don’t get me started on the topic if there is any sense in doing so. We have to deal with it.

There certainly are functions that deliver the correct time for the current timezone. But what if you would like to know the switch dates in advance? The rule for DST switch dates in Germany is quite simple:we switch to summertime at 2:00 in the morning on the last sunday in march and back to wintertime at 2:00 in the morning of the last sunday in october. So these dates are variable.

Here the PHP DateTimeZone comes to the rescue. The steps are simple enough:

  1. Get a DateTimeZone object for the timezone you’re interested in
  2. Get the transition dates for the year you are interested in by specifying the start and end dates to search for
  3. Clean up the returned array, since it always contains the start date itself

And here is a short piece of code to use:

The result is an array with two elements. For 2018 in Germany the results are:


0 comment

Use a private repository as source of a composer package

Sometimes I need to make a small change to a composer package, often in a Symfony project. It is a really bad idea to just go into the vendor directory of the package and change some code. It’s much better to fork the corresponding repository, apply your change and build a new release. Then you can use that in a composer.json file.

Fork the repository

For the purpoe of demonstration I will create a customized version of Javier Eguiluz’s EasyAdmin bundle for Symfony. So go to the github page of the EasyAdmin bundle and click on the “Fork” button in the top right corner. Github will create a fork for you under your own user account. Clone that repository and make your changes. For this is one line in the file src/Form/Util/LegacyFormHelper.php as I mentioned in the last posting.

Build a new release

Now we’re ready to build a new release. Go to the “releases” tab in your forked repository and click on “Draft a new release”. Define a new tag version (unimportant how you call it, I normally just count up the original release version). I normally enter something like “for private use only” into the “Release title” field but you just can leave that empty. Once you’re done you can submit via “Publish release”. You will be brought back to the release list and see your new release tagged with a green label saying “Latest release”. You just built your first release \o/

Use the release in a composer.json file

You now can change your composer.json file. First you need to add the repository. By default composer will look up the packagist repository. If you define a different one in the json file this local one will be searched first before falling back to the public repo. So we need to create a repository section and list the github repository. Mine looks like this:

The type is “vcs” (version control system) and the URL is your forked repository. I like to keep forks in a organization of its own called “vmgforks”. Now we can require the package by using its original name and the required version just is “*”:

Now update the composer.lock and download and install the package by:

Now you can check if the change made it to the vendor directory.


Getting to work the CKEditor plugin for EasyAdmin in Symfony 4

Developing with Symfony 4 can sometimes be a bit challenging as some of the most widely used bundles are not yet ported to Symfony 4 or never will be (like FOSUserBundle). And sometimes a bundle works pretty well but one of its third party plugins/bundles doesn’t. This is the case with the brilliant EasyAdmin bundle. Sometimes you might want to offer a WYSIWYG editor to a backend user. For this case there is a bundle called IvoryCKEditorBundle that integrates the famous CKEditor into the form component. But the Ivory bundle not (yet) supports Symfony 4 so a helpful soul created a fork and called the package hillrange/ckeditor so you can use CKEditors in nearly any form.

Nearly any but not EasyAdmin. We come to that later. First let’s see how it would work if it worked (that is a sentence, isn’t it?). In Symfony 4 the EasyAdmin config can be found in config/packages/easy_admin.yaml. For a simple entity that only contains a text attribute (of type “text” who would have guessed?) that we would like to WYSIWYG edit it would look something like this:

The field type is called “ckeditor”. For this to work EasyAdmin has an array of supported field types and this out of the box also contains an entry for the ckeditor type. It can be found in vendor/javiereguiluz/easyadmin-bundle/src/Form/Util/LegacyFormHelper.php and is called $supportedTypes. And this is why the Hillrange package doesn’t play well with EasyAdmin. The form class just has another name. The original line reads

and can be changed into

Doing so in the original EasyAdmin bundle in the vendor directory is a bad idea. My approach is a bit overkill but offers a clean and regular approach:

  1. Fork the EasyAdmin bundle on github
  2. Change the incriminating line as proposed
  3. Build a release of “your own EasyAdmin”
  4. Include that with the composer.json file to be pulled directly from github

How the latter works will be subject to the next posting. So stay tuned ;)

PS: At some point in the future the IvoryCKEditorBundle will be Symfony 4 ready (at least I hope so) and you will be able to turn back the composer.json entry to the original package.

0 comment

Docker based dev environment with PHP 7, MariaDB, phpMyAdmin, Mailhog & ELK stack

Docker can be used as a flexible development environment for (web) applications. With docker-compose you can add up several services to a complete scenario. Here I would like to present a new setup that contains a lot of things to make a developers life more comfortable, notably:

If you don’t need all these components, you always can disable whatever you’re not going to use. Your application will reside in the html subdirectory, the MySQL/MariaDB db files will be in the mysql directory so nothing is lost when you shut down the services.

If you need something else (PostgreSQL e.g.) please let me know and I will add it. Have fun!

0 comment

Run Oxid CE V6 locally using Docker and docker-compose

Recently the public availability of Oxid eShop V6.0.0 was announced. And it finally runs with PHP7 and is a major step towards a modern and comfortable web shop.

If you would like to test it locally or develop with it there are many options. Some time ago another one, flexible and versatile, opened: Docker.

In this GitHub repository I assembled an environment with:

  • Apache webserver with PHP 7.1 and all extensions needed (and xdebug)
  • MariaDB
  • phpMyAdmin
  • ELK stack to analyse and show apache log files

If you encounter any problems or bugs please file an issue with GitHub. I’m here and on Twitter to answer any question you might have. Have fun!


How to install dependencies from a requirements.txt file with conda

Just a little reminder: pip has this very useful option to install a bunch of packages from a single text file mostly called requirements.txt. Anaconda’s command line tool conda doesn’t support this option directly. It does support reading the package names from a file using the –yes and –file option

but that does not automatically install all the dependencies. To do this, we need to iterate over the file and install each package in “single package mode”:

Thanks to Luis Capelo for this snippet which I use to install dependencies in a dockerized instance of Anaconda / Jupyter (more on that in a later post).

0 comment

Docker automation for PHP Developers using Python


This posting will deal with using Docker on the developer desktop. I will not talk about deploying these containers to other stages of the track to production. Maybe this is a topic for a follow-up by me or by someone who is more apt with all things devops.

All this started when I realized, that docker-compose.yml needs an absolute path on the host for its shared volumes. This is OK but when you would like to have multiple development setups for multiple projects. What I wanted was a single config file to rule a complete set of Dockerfile and docker-compose.yml files. And a comandline tool to manage that environment without the need to juggle around with several other tools and numerous options and flags.

An intermediary state consisted of a Makefile with several shell scripts for all the stuff that was hard to do in Makefiles. It worked but was a bunch of files. I wanted something cleaner with more possibilities for the future and fewer helper files.

So here it is: a Python file to rule them all (sorry for the pun …) and build Dockerfile and docker-compose.yml from templates and a config.yml file when booting up the environment. The repository is here:

What you get

  • An Apache running PHP7.1 on http://localhost with document root (/var/www/html) as a shared volume in the www subdirectory
  • A MySQL database connected to that PHP container
  • A PHPMyAdmin listening on http://localhost:8080


  1. Check out from the Github repo above. Don’t mind the actual path to your environment. This will be determined and inserted into the docker-compose.yml file by the Python script.
  2. Install the required Python modules with
  3. Have a look at the templates in the templates subfolder
  4. Edit the configuration options in config.yml
  5. Boot the setup using
  6. Have a look at the running containers with

What doesn’t work yet

Using ./dockshell sshweb and ./dockshell sshsql to log into the running containers. Was not able to enter interactive mode. You will have to use:


  • ./dockshell clean removes all containers and images. And I mean all of them. This needs to be fixed!