You are reading articles by Simplificator, a Swiss-based custom software development agency. Here we write about the problems we solve and how we work together.
Die Welt verändert sich, und die Unternehmen müssen sich mit ihr verändern. Es reicht nicht mehr aus, dass sich die Unternehmen auf ihre traditionellen Geschäftsmodelle konzentrieren. Sie müssen sich auch der digitalen Transformation stellen, wenn sie in der neuen digitalen Wirtschaft überleben wollen. Aber was genau bedeutet "digitale Transformation" und wie können Unternehmen sie erreichen? Hier sind einige nützliche Tipps, wie Innovationen die digitale Transformation unterstützen können:
Die digitale Transformation ist eine Herausforderung
Der Wandel betrifft Menschen, Kultur und Prozesse. Bei der digitalen Transformation geht es nicht nur um Technologie. Es geht darum, wie Sie Ihr Unternehmen so verändern, dass es in Zukunft kundenorientierter und agiler wird. Um dieses Ziel zu erreichen, müssen Sie verstehen, welchen Nutzen Ihr Unternehmen aus der digitalen Transformation zieht und wo es derzeit steht.
Dies kann durch die Betrachtung von vier Dimensionen erreicht werden:
Prozesse (Werden veraltete Prozesse modernisiert, können Sie effiziente Workflows beschleunigen und deren Produktivität steigern)
Menschen (Übergang von einzelnen Mitarbeitern zu vernetzten Teams)
Kultur (Übergang von einer Befehls- und Kontrollkultur zu einer gemeinsamen Identität)
Technologie (Übergang von monolithischen IT-Systemen zu Microservices)
Lösen Sie das richtige Problem
Der erste Schritt bei jedem Projekt zur digitalen Transformation besteht darin, das Problem, das Sie lösen wollen, zu definieren und nicht einfach mit einer Idee zu beginnen. Deshalb ist es wichtig, dass Sie Ihr Team zusammenbringen und ihm Zeit geben, ein Brainstorming über die Art der Probleme zu machen, mit denen es konfrontiert ist. Danach gilt es herauszufinden, wie Technologie zur Lösung dieser Probleme beitragen könnte. Der Schlüssel dazu ist die Einsicht, dass es bei der digitalen Transformation nicht darum geht, Menschen zu ersetzen, sondern darum, menschliche Fähigkeiten zu entwickeln und zu verbessern. Besonders am Anfang lassen sich zum Teil mit einfachen Schritten grosse Vereinfachungen erreichen.
Die Verwaltung von Talenten und der Aufbau digitaler Fähigkeiten sind zwei Möglichkeiten, wie sich Unternehmen auf zukünftiges Wachstum vorbereiten können. Das ist unabhängig davon, ob sie die Implementierung einer komplexen Technologie wie AI planen oder lediglich ihre IT-Infrastruktur aktualisieren. Unternehmen sollten auch in die Schulung ihrer Mitarbeitenden investieren, damit diese die Technologie effektiver nutzen können. So wird sichergestellt, dass alle Zugang zu den Tools haben, die für die Ausführung bestimmter Aufgaben (wie die Verarbeitung von Kundendaten) benötigt werden.
Finden Sie die richtigen Technologie- und Lösungspartner
Sie werden Technologie- und Lösungspartner finden wollen, die Ihre Strategie der digitalen Transformation unterstützen können. Im Folgenden finden Sie einige Tipps, wie Sie dies tun können:
Verstehen Sie die Vorteile der Zusammenarbeit mit einem Technologiepartner: Ein Partner kann Ihrem Unternehmen helfen, Zugang zu den neuesten Spitzentechnologien zu erhalten, aber er verfügt auch über umfassende Erfahrung mit der Implementierung neuer Lösungen, die sich in anderen Unternehmen bewährt haben.
Finden Sie die wichtigsten Kriterien für die Auswahl eines Partners: Stellen Sie sicher, dass Sie klare Anforderungen an die einzelnen Anbieter haben, bevor Sie sich für einen Anbieter entscheiden. So werden Sie später keine Überraschungen erleben, wenn Sie Zeit damit verbringen, die Produkte oder Dienstleistungen der anderen Anbieter zu bewerten.
Erstellen Sie eine umfassende Liste potenzieller Anbieter auf der Grundlage dieser Kriterien
Anbieter bewerten: Nehmen Sie Kontakt zu den Anbietern auf und bitten Sie sie um detaillierte Informationen über ihre Produkte oder Dienstleistungen sowie um Fallstudien von anderen Kunden, die sie erfolgreich eingesetzt haben.
Arbeiten Sie mit dem besten Anbieter für Ihre Bedürfnisse zusammen: Wenn Sie den richtigen Partner gefunden haben, ist es an der Zeit, mit ihm einen Plan für die Einführung der neuen Technologie zu erarbeiten.
Lassen Sie sich nicht zu viel verkaufen. Lösungspartner leben davon, die Probleme als grösser darzustellen als sie sind, und vertrauen darauf dass ihre Kunden nicht genug technisches Selbstbewusstsein haben.
Trends und Innovationen pragmatisch bewerten
Um Ihr Unternehmen auf dem Weg der digitalen Transformation zu begleiten, ist es wichtig zu verstehen, wie Trends und Innovationen helfen können. Der erste Schritt besteht darin, diese Entwicklungen aus einem pragmatischen Blickwinkel heraus zu bewerten. Sie müssen nicht nur die Technologie, sondern auch den Business Case, die Personalprozesse und die Auswirkungen auf die Kultur betrachten. Ihr Ziel sollte es sein, eine Lösung zu finden, die mit Ihrer Vision für die Zukunft übereinstimmt und gleichzeitig die aktuellen Anforderungen innerhalb eines angemessenen Zeitrahmens erfüllt.
Testen und pilotieren Sie neue Technologien, aber nur dort, wo es sinnvoll ist
Die digitale Transformation ist kein Projekt, das für alle passt. Sie erfordert eine sorgfältige Berücksichtigung des Kontexts und der Kultur Ihres Unternehmens sowie der Bedürfnisse und Fähigkeiten Ihrer Mitarbeiter. Ihre Lösung kann nicht einfach lauten: "Wir setzen Technologie ein, um dieses Problem zu lösen." Sie müssen sich Gedanken darüber machen, welche Art von Technologie für Ihre spezielle Situation am besten geeignet ist, wer sie nutzen wird und wie diese Personen mit ihr interagieren werden.
Wir arbeiten mit Unternehmen zusammen, um wirkungsvolle Anwendungsfälle zu identifizieren, zu priorisieren und umzusetzen. Auf diese Weise können Kunden schnell Werte schaffen und gleichzeitig demonstrieren, was digitale Technologien und Arbeitsweisen für das Unternehmen leisten können. Der Prozess umfasst drei Phasen:
Innovation (Erstellung eines Machbarkeitsnachweises und Validierung des Geschäftsszenarios).
Inkubation (Einführung eines minimal realisierbaren Produkts und Testen und Lernen mit agilen Sprints).
Industrialisierung (Ausführen der Technologie und des Geschäftsprozesses in grossem Massstab).
Nach einer ersten Welle von Anwendungsfällen wiederholt sich der Prozess mit der nächsten Welle – und so weiter. Was in den verschiedenen Phasen umgesetzt wird ist nicht nur eine Frage des gesunden Menschenverstandes, sondern auch entscheidend, um die Zustimmung Ihres Teams zu erhalten und die Kosten überschaubar zu halten. Wenn Sie neue Technologien ausprobieren ohne zunächst zu verstehen, warum sie für Ihr spezielles Geschäftsproblem oder Ihre Geschäftseinheit geeignet sind, könnten Sie viel mehr als nötig in Testversionen investieren, die nie von jemandem im Team verwendet werden (und daher nutzlos sind). Andererseits sollten Sie, wenn Sie bahnbrechende Innovationen wie Chatbots oder künstliche Intelligenz (KI) testen, nicht einfach das für bare Münze nehmen, was deren Anbieter Ihnen sagen.
Arbeiten Sie Agil
Klassische Projektkonzepte und Projektplanungen haben bei IT-Projekten oft zu Kostenüberschreitungen und Lieferverzögerungen geführt. Dies passiert in den letzten Jahren seltener: Neue Arbeitsmethoden erlauben besser während der Entwicklung auf unbekannte oder unbewusste Komplexitäten einzugehen. Diese Methoden werden unter den Überbegriff “Agile Entwicklung” zusammengefasst. Nicht nur IT-Projekte, sondern das ganze Betriebsmodell einer Firma kann von einer agilen Vorgehensweise profitieren. Damit können Projekte besser auf die individuellen Bedürfnisse der Firmen eingehen.
Transformieren Sie Arbeitsweisen und das Betriebsmodell. Agile Arbeitsweisen ermöglichen es Unternehmen, schnell auf Veränderungen zu reagieren. Daher ist die Unterstützung von Unternehmen bei der Einführung von Agilität eine wichtige Säule unserer Beratung zur digitalen Transformation. Wir verankern die Verhaltensweisen und die Kultur, die die funktionsübergreifende Zusammenarbeit, iterative Entwicklung und einen neuen Lernansatz fördern – einen, der es Menschen ermöglicht, sich mit digitaler Geschwindigkeit anzupassen und innovativ zu sein. Wir zeigen Führungskräften, wie sie Agilität im gesamten Unternehmen einsetzen können. Und ebenso wichtig ist, dass wir daran arbeiten, Governance, Prozesse und Organisationsstruktur an einem stärker plattformgesteuerten – und weniger isolierten – Betriebsmodell auszurichten.
Vergessen Sie nicht die Menschen und die Kultur
Dies ist der wichtigste Aspekt der Innovation, insbesondere wenn es um die digitale Transformation geht. Menschen sind nicht nur eine Ressource, sondern auch ein Vermögenswert. Der Erfolg eines Unternehmens hängt von seinen Mitarbeitern ab: Sie sind die Hauptakteure bei der Gestaltung der Unternehmenskultur und tragen zum Erfolg oder Misserfolg des Unternehmens bei. Sie können noch so tolle Ideen haben, wenn Sie kein Team haben, mit dem sie umgesetzt werden können, werden sie nicht zum Tragen kommen.
Die digitale Transformation ist eine Herausforderung, aber wenn man sie Schritt für Schritt angeht, kann man seine Ziele erreichen. Die digitale Transformation selbst ist eine Reise, kein Ziel an sich.
Wenn Sie Ihr Unternehmen auf die nächste Stufe bringen und eine Informationsflut vermeiden möchten, können Sie viel Zeit sparen, indem Sie unser kostenloses Digital Transformation Consulting in Anspruch nehmen. Wir arbeiten mit Ihrem Team zusammen und können umgehend Empfehlungen zum Aufbau digitaler Fähigkeiten, zur Datenintegration und zur Verbesserung der IT-Infrastruktur abgeben
Wir freuen uns darauf, Sie auf Ihrem Weg zu begleiten.
Visuelles Design ist entscheidend für den Eindruck, den Software bei Nutzern hinterlässt. Das hört sich einfach an, aber wenn es nicht durchdacht ist, wird es die User Experience beeinträchtigen und kann Ihren gesamten Softwareeinsatz in Frage stellen. Der Look & Feel Ihrer Software ist für den Erfolg Ihrer Software genauso wichtig, wie Ihre Datenbankstruktur oder andere Programmelemente.
Bei Simplificator integrieren wir uns in jedes CSS-Framework, das unsere Kunden verwenden, egal ob es sich dabei um ein massgeschneidertes oder ein Standard-Framework wie Bootstrap handelt.
Wenn wir jedoch Softwareanwendungen von Grund auf entwickeln, ist unser bevorzugtes Framework Tailwind CSS.
Was ist Tailwind CSS?
Webentwicklung ist anspruchsvoll. Es gibt immer viele komplexe Aufgaben, um moderne Applikationen zu erstellen. Die Gestaltung des Frontends und jeglicher sichtbaren UI Elemente ist da keine Ausnahme. Die Zuordnung von Styling-Effekten kann mühsam und zeitaufwändig sein, die Entwicklung der Webanwendung signifikant hinauszögern, und die Kosten der Programmierung erhöhen.
Mit Tailwind CSS können Sie auf effiziente Weise schöne benutzerdefinierte Benutzeroberflächen erstellen. Tailwind CSS ein hochgradig anpassbares Low-Level-CSS-Framework, das es uns ermöglicht, definierte Designs schnell und effizient zu erstellen.
Vorteile von Tailwind CSS
✅ CSS-Properties als Klassen: Alle CSS-Properties gibt es als Klassen, womit man das Mapping von CSS Properties zu Klassen nicht selber machen muss. Man kann trotzdem einfach Klassen kombinieren zu neuen Klassen, welche in der Applikation Sinn macht.
✅ Auf Wiedersehen CSS-Datei-Wald: Tailwind CSS macht es einfach, vordefinierte CSS Klassen direkt in HTML zu integrieren. Anhand dieses Rahmens können die Komponenten individuell gestaltet werden; Entwickler*Innen müssen nicht zwischen HTML und CSS Dateien hin und her wechseln.
✅ Keine Kompromisse: Das Design ist komplett an die Wünsche des Kunden anpassbar, Kompromisse müssen nicht eingegangen werden. Trotz dieser genauen Anpassung minimieren wir bei Simplificator wir die Dauer (und somit Kosten) des entsprechenden Programmieraufwandes dank Tailwind CSS deutlich.
✅ Moderne Komponenten: Mit Tailwind können auf ein umfangreiches Angebot an externen Tailwind-Komponentenbibliotheken zugreifen, die Ihre Anwendung modern und Benutzerorientiert macht.
✅ Mobile First: mit Tailwind implementieren wir komplexe responsive Layouts die Ihre Applikation von Desktop, über Mobiltelefone und IPads hin glänzen lassen. Der Programmieraufwand hierfür, sowie die damit verbundenen Kosten, gestalten sich mit Tailwind effizient und ökonomisch.
✅ Klein und schnell Mit zunehmender Grösse Ihrer Applikation steigt auch die Grösse der CSS-Datei. Dies ist bei Tailwind jedoch nicht der Fall: Tailwind kann mit PurgeCSS optimiert werden kann. PurgeCSS kann die CSS Dateigrösse erheblich reduzieren, indem es HTML durchsucht und nicht verwendete Klassen automatisch entfernt. Sie müssen Ihre HTML und Ihre CSS Dateien nicht mehr händisch aneinander anpassen. Die CSS Elemente Ihrer Anwendung werden so klein wie möglich gehalten.
Wir helfen mit Ihrer Migration zu Tailwind
Wenn Ihre Anwendung sehr umfangreich ist, kann der Einsatz von Tailwind CSS für Sie von Nutzen sein. Simplificator hat Erfahrung in der Überführung bestehender, grosser Applikationen zu Tailwind CSS. Wenn dies für Sie von Interesse ist, melden Sie sich bei uns! Wir besprechen gern, was möglich ist und in Ihrem Anwendungsfall Sinn macht: info@simplificator.com Bis dahin!
Rails has very good documentation in general and an upgrade guide in particular, but an upgrading task can still be quite tricky and intimidating. None of the documentation covers all the details and sometimes details are the key to overcome challenges that can arise when migrating to a newer Rails version.
I would like to share some tips that I learned from my colleagues and that helped me a lot with developing an upgrade strategy.
The general idea is: before doing Rails update itself, try to update as many dependencies as possible in advance. (Bonus: this strategy can be used for any framework upgrade - for example, I applied this approach when upgrading the application made with Gatsby). The reason is: when you try to upgrade Rails directly, all packages are updated at once as well and you don’t understand where the errors come from. Did a new Rails version cause them? Or some of the gems?
When I once tried to do a Rails upgrade without updating dependencies in advance, all tests were broken. The error message was very weird and not helpful at all. Google and Stackoverflow also did not know about such a problem. I changed my approach and started to update gems one by one. It turned out that the database-cleaner gem, that our application uses, introduced some breaking changes since our last update (it actually became a set of gems depending on the used database adapters). In our case I had to install a new gem database-cleaner_mongoid and do some configuration changes. The problem was solved!
So let's have a look how an upgrade to a minor Rails version could be performed (for example, from 6.0 to 6.1). These steps suppose that Rails is pinned to a specific version in your Gemfile, for example gem 'rails', '~> 6.0.5'.
First of all you could try to update to the next Rails patch version (for example, from 6.0.3.6 -> 6.0.4.1) - this will update only Rails and no other dependencies. In that case you just run bundle update rails and you are done. You don’t have to run the app:update task.
The next step would be to run the command bundle outdated. It lists all outdated gems, pointing to what group each gem belongs to - default, development or test. Then you can update them one by one (you update dependencies only in the Gemfile, not in Gemfile.lock). One update - one commit. Do not forget to run tests after each gem update! Some updates are as simple as just running the command bundle update <gem name>. Others can be more complicated - then it is better to tackle them separately, in a smaller pull requests. For example, the upgrade from sprockets 3 to 4 requires also some changes in manifest.js. Or, for example, the mongoid upgrade to version 7 had some breaking changes, and I had to modify code in several controllers. It is better to not mix up such stuff with other gems updates.
It might seem like a lot of work because the list of dependencies can be pretty long (I ended up with one pull request updating 20 gems plus 4 pull requests for individual gem updates). But at the end of the day it saves you a lot of time since you can discover faster which dependency caused the errors after its update.
Another option to perform Rails upgrades smoothly is to keep your dependencies up to date. You can do it easily by installing dependabot. It will run your pipeline against any new gem updates and you will be able to catch breaking changes early.
Often before the Rails upgrade you would also like to upgrade to a newer Ruby version. Here the same principle is applied: if the upgrade does not work out of the box and you get errors, try to update first those dependencies that block the Ruby upgrade.
Here once again all steps recapped:
Upgrade Ruby to the latest version compatible with the desired Rails version
If this does not work, individually upgrade gems blocking the Ruby update, and try again
Update Rails to the most recent patch version of the currently used release series
Run bundle outdated and update all outdated gems one by one
Perform the Rails upgrade to a minor or a major version following the Rails upgrade guide
Success! 🎉
Keeping your Rails app up to date is essential. It allows you to use the latest features that will generally make your life easier, and ensures you don't miss important security updates. It'll also keep your developers team happy if they can work with cutting edge libraries!
Have you recently checked the size of your backlog?
There is a limit to the amount of work a team can do at a given time, so new tasks get queued in a backlog. As a project grows, so does its backlog. There are new features to develop, more bugs to fix, but these tasks take longer to finish than to write down.
The problem with large backlogs
Large backlogs are demoralizing. It is intimidating to realize how much is left to do.
Large backlogs are overwhelming. People lose the overview. They create a second, smaller, "prioritized" backlog. Or they start tracking work through other channels: in-person meetings, email, text chat. That exacerbates the problem - now you have multiple backlogs and they all keep growing.
Large backlogs stagnate. The bigger the backlog, the more information is outdated and the more maintenance is required.
Large backlogs give a false sense of how much is really planned, because most items are too vague or not estimated yet.
Keep your backlog small(er)
Reducing the backlog size can reduce the team's stress level. It also allows the team to focus on what's the most important. Here are some ideas to help you declutter:
Acknowledge your backlog is too big. They all are. Discuss that with your team and agree on what you want to do about it.
Review the backlog as your priorities change. What you thought was important 4 months ago may not be as important now. Outright remove what has become irrelevant and reorder the rest to align with the new requirements.
Drop items from the end of the backlog. A little controversial, but if you keep the list in order of priority some items will always remain at the bottom. Why keep them at all if you never get around to them?
Don't plan too far ahead. Only bring the imminent and most concrete parts of the vision to the backlog. Consider keeping ideas which are not fully formed somewhere else.
Start fresh. This is a heavy-handed option. Archive the entire backlog. Create a new one from scratch. The important things will resurface.
Keep at it. Even with the strategies above you will slip occasionally. Set a calender reminder to reassess every few months.
As a small software company, we at Simplificator handle the entire hiring process on our own. We find that gives us the best results. I've been helping review job applications and interview candidates for more than 4 years. Here are some things I've observed that influence the success of an application.
Motivation letter
I look for two things in a motivation letter:
interest for the job position or company;
how the person's experience relates to the job offer.
Interest for the company
A single person has a big impact in a small company. That's why it's important that everyone finds their work meaningful and motivating. It's hard to tell if that's the case before the trial period, but you get a hint if you work through a representative problem together during technical interviews. If I have to choose who to interview, I'd rather pick candidates who've given enough thought about whether they'd like this particular job.
Show you've done research:
Write to the listed contact instead of "Dear Sir/Madam".
If the offer says fluency in a language is a requirement, write the motivation letter in that language. It's okay to keep your CV in another language.
Look for public information about the company (from its website, blog, sponsorships, conference talks, etc.) and mention something you like or identify with.
The last one is not about flattery. Even if you don't find anything "exciting" about the company, surely there's something you could get out of working there, besides money. Do you want to learn a specific skill? Do you want to gain experience in a company of a certain size? Do you want to change your work mode to improve your work-life balance? Answering such questions doesn't just help a company decide whether they want to work with you. It also helps you refine your job search.
Demonstrating how your experience fulfills the requirements
Don't just say "I fit the job description perfectly". Give concrete examples of how you meet the criteria in the job listing.
It's tempting to just rephrase the contents of the CV. Instead, try highlighting which skills or specific parts of past jobs relate to this offer.
Counter-intuitively, stating in which ways you don't fit the job description and how you plan to address that can play in your favour as well. Job offers often make it sound like companies are looking for a candidate who fits a certain mold. However, the right hire can also transform their job for the benefit of the entire team. If you're unsure about the strictness of the requirements, get in touch with the company to clarify. A phone call can give you a new perspective.
CV
Include experience from areas of work other than the core role for which you are applying. Your expertise will be valuable in a small company which cannot have a specialist in every field. As an example, here are some skills from seemingly unrelated domains that remain relevant at a software agency:
former translator - you have good writing skills, the languages you know could give access to new markets. This is particularly important in countries with multiple language regions, like Switzerland.
government job - you understand how procurement/tendering works
background in a niche industry - you understand domain processes and have ideas on how to optimize them; that could be an opportunity for a new product or a partnership
background in any client facing job - you know how to talk to customers, negotiate, etc.
General CV advice - like keeping it short and structuring it around impact - still applies.
Work sample
Companies may ask to send them a product of your work, especially for technical positions. Sometimes that is a take-home assignment, sometimes it's an extract from prior work.
Take-homes are time-consuming when applying for multiple positions, so we prefer a sample from existing work. We also request something similar for non-technical positions (see below).
Code sample
If you need to provide a code sample, make it easy to find and read. The reviewer won't know what to look for if you've linked your entire GitHub profile.
Point to a specific piece of code you're proud of or find interesting. That could be a class or module. It could be a single commit that fixes a bug with a commit message explaining when and why the bug occurs, why your fix works and what alternatives there are.
"I can't share code written for my current employer"
You don't have to. It's also okay if you don't have a side-project and don't code outside of work. However, if applying at multiple companies, consider creating something small that you can present to all of them.
You could:
try solving a problem you've encountered at a previous job in a new manner
contribute to an open source library you use: check the open issues, try to reproduce one. Attach a failing test case or a reproduction script. If you know enough about the project internals, you could even coordinate with the maintainers and open a pull request with a fix.
Other types of work samples
Your line of work does not involve coding? You can still describe how you work. Maybe you can share a blog post about how you solved a problem at work, or a presentation you've given about an achievement. Feel free to link to them in your cover letter or CV.
expect(pdf_pages[2]).to include( 'A rather long line from the PDF that was in the original test, ' \ 'but which I have substituted for the purposes of this example' )
It renders a PDF, then parses it with pdf-reader and asserts that some text is on page 3 of the document.
The expectation failed, but the diff showed that the text was on the page. However it was on two lines instead of one.
Sure, one could put a line break in the test and call it a day:
expect(pdf_pages[2]).to include( "A rather long line from the PDF that was in the original test, " \ "but which I have substituted for the purposes of this\nexample"# Note the \n )
I didn't give up so easily.
The motivation
As an agency, we have our set of practices and documentation about running software. That makes provisioning, monitoring, backups, knowledge sharing, etc. easier. The application in question was an exception. It had been built by someone else and had been in production for years before Simplificator took over development and maintenance. We wanted to move it to our infrastructure eventually, but we had decided to get familiar with the code first.
After a few months of developing new features and fixing bugs, we knew enough to migrate to a new server with more confidence. Running the application in Docker was one step of the process and this is when I ran into the test failure above.
I did not cheat and change the test, because even though it looked like an insignificant detail, it could be something more. Whenever you make an infrastructure change you find things that were assumed, but undocumented, things that were done once manually and forgotten. We had written the PDF generation test in the phase when we were getting to know the codebase. Now this test was helping us consistently observe a difference in behaviour between two environments (Docker and no Docker). A rare chance!
The search
The application generates PDF files using wkthmltopdf. That is, Rails renders an HTML template, then wkhtmltopdf converts the HTML document into a PDF. The problem could be in any of these, so I tried to narrow it down.
First, I checked the page dimensions. A narrower page would have shorter lines. That was not it. wkhtmltopdf saves A4-formatted pages by default. The page margins were also expressed as absolute numbers.
Then I tried to open the PDF generated withing Docker with the PDF viewer on my host. I wanted to get the PDF from the test. The test has everything set up to render the exact document that reproduces the bug. In the application I would have to fill out some forms, which takes much longer. I ran into some permissions problems getting the file out of the container. I went down that rabbit hole for longer than expected (as one does).
Frustrated, I tried at least generating the PDF from outside a container and copying it into the container for comparison. I ran the test outside Docker, opened the PDF and knew immediately what the problem was.
The realization
The font in the PDF I had just built looked slightly different from the font I'd seen in documents generated in production.
I found the CSS rule:
font-family: Helvetica, Arial, sans-serif;
The developer who wrote the test was using macOS, so the Helvetica font was present.
The production Linux server had neither Helvetica nor Arial. It did have a different replacement font that was apparently close enough in dimensions:
The tests had so far been running on the default image provided by the continuous integration service. That image is based on Ubuntu and has many packages pre-installed, so it probably also had a close-enough fallback.
The new Docker image, though, only had the bare minimum needed to run the application. It didn't even have Deja Vu Sans. So it must have been using a different sans serif font, which has wider shapes, making less text fit on a line.
Sure enough, including Nimbus Sans in the Docker image as a fallback for Helvetica fixed the test.
Hin und wieder werde ich gefragt, was man beachten muss, wenn man sich Mitte 30 nochmals beruflich neu orientiert. Ganz einfach: Mut fassen und Prioritäten setzen. Klar ist das nicht so einfach, wie es klingt. Klärt man für sich jedoch einige wesentlichen Punkte, wird aus dieser komplexen Entscheidung ein gangbarer Weg sichtbar. Meiner sah so aus:
Schritt 1: Wissen, was man nicht will. Bevor ich mich für den Karriereschritt zur Softwareentwicklerin entschied, habe ich lange im Journalismus gearbeitet und war danach als Fotografin selbstständig. Letzteres erforderte eine grosse Flexibilität in Bezug auf Arbeitszeit (z.B. Wochenendaufträge), was mit meinem Privatleben langfristig nicht vereinbar war. Auch wusste ich, dass das Thema Kundenakquisition mir persönlich sehr viel abverlangte. Ganz gleich in welcher Branche - eine künftige Tätigkeit sollte diese beiden Aspekte nicht beinhalten.
Schritt 2: Wissen, was man will. Da ich zu dem Zeitpunkt bereits eine Familie hatte war klar, dass ein mehrjähriges Studium nicht infrage kam. Ich suchte also nach einem schnellen Einstieg in eine neue Branche. Mir war wichtig, einen “echten Skill” zu beherrschen. Das neue “Handwerk” sollte mir zudem karrieretechnisch Sicherheit verschaffen. Last but not least war mir das Arbeitsumfeld sehr wichtig: gute Kolleg*innen, ein Büro, in dem man sich trifft, Arbeitsprozesse, die unkompliziert ablaufen. Auf dieser Grundlage wurde mir sehr schnell klar, dass eine Ausbildung im Tech-Bereich für mich infrage kam.
Ich hatte bereits Erfahrung in der IT-Branche gesammelt, während ich als Intranetportal Editor in einer grossen IT Firma in Moskau arbeitete. In dieser Funktion habe ich Artikel über unsere Software-Produkte geschrieben und mein Interesse daran, wie Software tatsächlich gebaut wird, wurde immer grösser. Zudem habe ich die Atmosphäre und die Menschen sehr geschätzt. Ich habe festgestellt, dass meine Kolleg*innen ähnlich denken wie ich und so auch gemerkt, dass ich gerne wieder in der IT arbeiten möchte, aber diesmal mehr als Techie.
Schritt 3: Informationen und Touchpoints. Ich war nicht sicher, ob ich mit meinem Background Entwicklerin werden könnte und dachte erst mehr an eine Position wie z.B. Product Manager. Aber bei der Recherche habe ich festgestellt, dass ich dennoch eine technische Grundausbildung benötige, und, was noch viel wichtiger ist, Erfahrung in der Entwicklung. Also habe ich mich entschieden, ganz von vorne zu beginnen und Webentwicklung zu lernen.
Dazu las ich viele Blogposts von anderen Frauen, die den Quereinstieg geschafft hatten und fühlte mich dadurch ermutigt.
Schritt 4: Ausbildung. So habe ich angefangen, mich über praxisnahe Ausbildungsmöglichkeiten schlau zu machen und ich rate allen, sich damit zu befassen, welche Angebote online oder auf deinem lokalen Markt existieren und dich mit Studierenden oder Alumni der Schule auszutauschen. Gerade im IT-Bereich existiert eine Vielzahl an Anbietern, die mit Crashkursen zum Einstieg in die IT-Karriere werben. Persönlich war für mich klar, dass ich die Ausbildung Vollzeit absolvieren wollte, sie jedoch nur einige Monate dauern sollte. So habe ich mich für einen dreimonatigen Full-Stack Programmierkurs bei Propulsion Academy angemeldet. Die Lernerfahrung war intensiv, jedoch sehr bereichernd.
Schritt 5: Vernetzen, Vernetzen, Vernetzen. Nun hatte ich 3 Monate Programmieren im Rucksack und war voller Hoffnung, eine Anstellung als Junior Softwareentwicklerin zu finden. Entwicklerinnen sind auf dem Arbeitsmarkt bekanntlich sehr begehrt. Schnell musste ich jedoch feststellen, dass dies nicht zwingend für Junior Positionen oder gar Praktika gilt. Auf viele meiner Bewerbungen habe ich keine Rückmeldung erhalten. So schlug ich einen anderen Weg ein. Anstatt mich auf Ausschreibungen zu bewerben, ging ich proaktiv auf interessante Personen oder Unternehmen zu und nahm an Hackathons und Meetups teil. So wurde ich auch auf Simplificator aufmerksam - und sie auf mich. Simplificator führt in ihrem Büro ein wöchentliches Coding-Meetup zu Ruby on Rails durch. Nachdem ich an einem weiteren Meetup bei Simplificator zum Thema Testing teilnahm und mir die Atmosphäre dort sehr gut gefiel, nahm ich meinen Mut zusammen und fragte, ob sie ein Praktikum anbieten. Kurz darauf traf ich mich mit unserem CEO Lukas und durfte dann als Praktikantin starten. Nun bin ich einer Festanstellung als Junior Softwareentwicklerin tätig und mache das, was ich am Anfang meines Karrierewechsels wollte.
Ich wünsche allen, die mit einem Einstieg in die Tech-Branche liebäugeln viel Erfolg, Mut und Ausdauer. Dranbleiben lohnt sich.
Inhalt: Tatiana Panferova
Text und Übersetzung: Patricia Leventis, Miriam Schütz
So organisieren wir uns in dieser aussergewöhnlichen Zeit
Es ist eine Zeit mit vielen Herausforderungen, sowohl geschäftlich als auch im privaten Umfeld. Man startet in den Tag mit einem Update zu den Zahlen rund um das Coronavirus und wird täglich mit einem Anstieg der Erkrankten und Todesfälle konfrontiert. In der Schweiz sind inzwischen 56 Personen am Coronavirus gestorben, 6113 sind infiziert. (Stand 22.03.2020, 10:30 Uhr) Der Bundesrat hat die «ausserordentliche Lage» ausgerufen.
Um das Wachstum dieser Zahlen zu verlangsamen, hat der Bundesrat verschiedene Massnahmen ergriffen - unter anderem das Einschränken des öffentlichen Lebens. Doch physische Distanz heisst nicht gleichzeitig soziale Distanz. Gerade in Zeiten wie diesen ist Kommunikation extrem wichtig. Gemäss einem unserem Grundsätze “dare to question” steht bei uns auch in der aktuellen Situation Kommunikation an oberster Stelle. Wir entwickeln nicht einfach drauf los, sondern wir finden zuerst heraus, was unsere Kunden benötigen. Dazu gehört auch, dass man als Team eng zusammenarbeitet und sich permanent austauscht.
Doch wie erreichen wir das trotz Homeoffice bzw. den Einschränkungen durch das Coronavirus?
Unseren gemeinsamen Tag beginnen wir jeden Morgen mit einem virtuellen Standup Meeting via Zoom. Das Ziel ist ein kurzer Austausch über die Aufgaben jedes Mitarbeiters und jeder Mitarbeiterin und ob man auf Projekten zusammenarbeiten kann, um sich gegenseitig zu unterstützen. In diesem Zusammenhang haben wir auch einen Blick auf Moco, unser Planungs- und Zeiterfassungstool. Die Planungsübersicht zeigt uns übersichtlich welcher Mitarbeiter in den kommenden Tagen auf welchem Projekt arbeitet.
Da auch ein Arbeitstag im Homeoffice nicht um 12 Uhr vorbei ist, treffen wir uns im Team noch einmal am frühen Nachmittag zu einem virtuellen Coffee-Break. Diese tägliche Kaffeepause gibt Raum für Themen, die nicht zwingend mit der Arbeit zu tun haben und fördern das soziale Miteinander in dieser aussergewöhnlichen Situation.
Regelmässige Videocalls über den Tag verteilt helfen uns, uns in kleineren Teams abzusprechen, Fragen zu stellen und uns auszutauschen sowie etwas zu diskutieren. Auch mit Kunden und Leads stimmen wir uns aktuell über diesen Kanal ab.
All unsere Systeme sind von zu Hause erreichbar und wir sind uns bereits gewohnt ab und an remote zu arbeiten. Slack erweist sich dabei für uns als unerlässliches Tool zur textbasierten Kommunikation untereinander als auch mit unseren Kunden. Unser Grundsatz “Collaborate closely” nimmt noch mehr an Bedeutung zu, damit wir in dieser Zeit die Bedürfnisse unserer Kunden erkennen und auch lösen können. Wir stehen in direktem, regelmässigen Kontakt mit jedem Einzelnen und versuchen dort zu helfen, wo es uns braucht.
Doch neben all den technischen Möglichkeiten, die uns die Zusammenarbeit erleichtern ist es wichtig, dass man sich zu Hause ein geeignetes Umfeld zum Arbeiten schafft. Ein separater Arbeitsplatz an dem man sich besser auf die Arbeit konzentrieren kann, ist enorm hilfreich. Darüber hinaus hilft ein strukturierter Tagesablauf mit fixen Pausen z.B. für Sport.
Allerdings sehen wir auch, dass Homeoffice nicht für alle Branchen umsetzbar ist. Was macht der Blumenladen um die Ecke, dessen Lager mit frischen Blumen voll ist? Was macht das Geschäft mit Kinderkleidern, welches die aktuelle Frühjahrskollektion bestellt, aber nun stationär nicht verkaufen darf? Ein Webshop kann hier vielleicht Abhilfe schaffen, so dass auch diese Unternehmen weiterhin für ihre Kunden da sein können. Wir sind dabei, uns einfache Lösungen zu überlegen.
Für Unternehmen, die von zuhause aus arbeiten können und ihre eigenen Server im Büro haben, lohnt es sich, ein VPN einzurichten und sicherzustellen, dass jeder Mitarbeiter auf einfache Art auch remote Zugriff hat.
Wir sehen, dass besonders in Zeiten des Coronavirus eine enge Zusammenarbeit und der Austausch untereinander wichtig sind. Natürlich wären direkte Kontakte vor Ort in vielen Fällen besser - die digitalen Varianten sind aber gute Alternativen.
Gerne beraten und unterstützen wir, sollte jemand Hilfe benötigen in Bezug auf Remote Collaboration - technischer oder auch organisatorischer Art.
Physical distancing doesn't mean social distancing - rather collaborate closely.
There is one obvious way that makes it easier for coders to write blog posts.
We tried everything before: First we wrote our own thing. Of course. It was a simple database and we wrote our own
markup parser - well, it was 12 years ago and there wasn't much around rails yet. And for the first year or so, it
was just a blog. After some time
Radiant CMS came out and we gave it a spin. It worked, it was quite ok. We struggled greatly
with the multilingual part, but had something running. Unfortunately I don't have screenshots of the blog - and the
wayback machine
has no recollection of our CSS, so I won't post screenshots here. It wasn't grand either, but already fairly political
(I ranted about the SUISA fees, which is now the reason why it is now apparently legal to use torrent software in Switzerland). I found a screenshot of the front page:
But it was also very technical, we were proud of working with Ruby on Rails, almost as much as we're proud now of
working with Elixir and Phoenix.
We then had the idea to link the different aspects of our work together: We write projects, using technologies,
with customers. Page visitors should be able to see what we do, who we are, and the connecting link was technology.
Several developers will develop a project, one project was always for one customer, one customer might have many projects. There will be several technologies used
(Ruby on Rails, Javascript in most cases, but also jQuery, Cucumber, RSpec, Heroku and many more). So we linked them
together. To make sure the links stay consistent we rolled our own thing again.
Simple is not easy. So our page grew, and it became apparent that we're inflexible. It got out of date. It was slow.
It wasn't ideal for all this new fancy SEO strategies. We expanded and tweaked. And our own system survived. But
we found out that we're so far behind that it's hard to catch up. Was it worth it?
We did a redesign, mostly to support mobile, and streamlined everything optically. But then we stopped:Our leads come from connections and people who experienced working with us, rarely through google. We needed to not
suck on our page, so we don't deter anyone, but even if we would triple our leads from the web site it would contribute
close to nothing to our bottom line. So we focused on other topics. To ease some pain with the blog, we moved it
to WordPress. A complete admission of defeat.
Last summer, things started to move again. We changed the way we organize ourselves and how we take decisions (more about
that later). So some of us took initiative and started rewriting, taking the best technologies available
to create a top-of-the-line solution, with deployment pipelines, static rendering, CDN and the best
of all, our blog content is now on GitHub. We can write however we like with the editor of our choice,
issue pull requests for feedback, and publish with a commit. And suddenly, we (or at least I) write blog posts again.
The issue why we procrastinate about stuff like writing blog posts is not the technology. Our habits and what we love to do define what comes easy. Procrastination is often a sign that we strayed away from what we're good at. We're not procrastinating about what we love to do. If that is writing code, committing and writing pull requests, let us hook into that.
So now, to write this blog post, I added a file to our repository (which is public on GitHub, by the way), and issued a pull request. I have asked others to pitch in, and after I took in all the feedback I got, this post will
be merged and published.
This is a way to make it easy for coders to publish blog posts.
To have a process like that is not easy to set up. But when it's done it is as it should be: simple.
Cypress.io has very nice tooling for testing. We have been experimenting with it in various projects, one of which is a Rails application.
Cypress is not the obvious choice for Rails, since Rails comes with system tests out of the box since version 5.1. Before that Capybara was also not hard to set up.
Over the years we've gone back and forth on Selenium-based tests mainly due to how easily they can become slow and flaky. We're now trying to see if Cypress can help in this aspect.
There are a few subtleties about integrating Rails with Cypress.
First of all, if your frontend communicates with the backend through an API, Cypress makes it easy to test the frontend in complete isolation. In this application however we are dealing with a classic server-rendered user interface that achieves some of the interactivity with "sprinkles" of JavaScript. That means that we have to run the Rails server in order to test the UI.
Cypress knows nothing about the backend and expects it to be running already. We can get there with a helper script:
#!/usr/bin/env bash
RAILS_ENV=test bundle exec rake db:environment:set db:create db:schema:load bundle exec rails server -e test -p 5002
Then we tell Cypress how to find it using the baseUrl setting in cypress.json:
{"baseUrl":"http://localhost:5002"}
Cleaning up between tests
Because the test backend is a long-running process and the tests can (indirectly) modify the database, we need to make sure every test starts with a clean slate.
One way to do it is to expose an API that is only available during tests.
# config/routes.rb
Rails.application.routes.draw do # ... if Rails.env.test? require'test_routes' define_test_routes end end
The necessary routes are defined in a separate file on purpose. First, the file name itself warns that they are for the test environment. Second, the conditional inclusion in the router is easy to scan and there's no chance to accidentally define test routes outside this conditional, no matter how many there are.
Let's define a route for the database cleanup:
# lib/test_routes.rb
defdefine_test_routes Rails.logger.info 'Loading routes meant only for testing purposes'
namespace :cypressdo delete 'cleanup',to:'cleanup#destroy' end end
The controller contains this:
# app/controllers/cypress/cleanup_controller.rb
classCypress::CleanupController < ActionController::Base defdestroy if!Rails.env.test? return head(:bad_request) end
tables = ActiveRecord::Base.connection.tables tables.delete 'schema_migrations' tables.eachdo|t| ActiveRecord::Base.connection.execute("TRUNCATE #{t} CASCADE") end
head :ok end end
The guard clause is there to be extra careful, because we then truncate all application-defined tables! We keep the migrations information intact and remove the data from all other tables. No need for a gem like database_cleaner.
Speaking about logging in, Cypress encourages you to "cheat" as much as possible in the test setup phase. (See Cypress best practices) Logging in using through the user interface is reserved for those tests that actually verify the login flow. Every other test can use a backdoor.
Login helper
# lib/test_routes.rb
deftest_routes namespace :cypressdo # ... resource :sessions,only:%i[create] end end
# app/controllers/cypress/sessions_controller.rb
classCypress::SessionsController < ActionController::Base defcreate sign_in(user) render json: user end
private
defuser if params[:username] User.find_by!(username: params.fetch(:username)) else User.first! end end end
The corresponding command can be defined as follows:
Now we can quickly login in tests with cy.login() (or cy.login('billie') to log in as 'billie').
Additional tips
You may have noticed that the /cypress/factories endpoint returns a JSON representation of created record. This makes it easier to inspect the data in the Cypress test runner interface (open the developer tools, and expand the response logged in the console).
It also allows you to use the returned data in the test, e.g.:
Another thing that makes testing smoother is configuring the Rails server to reload code on every request in the test environment. By default code caching is enabled and speeds up the test suite. However, if you are also changing backend code while writing Cypress tests, you'd have to manually restart the server on every change. We use the configuration below to get the best of both.
# config/environments/test.rb
Rails.application.configure do config.cache_classes =!ENV['CYPRESS_DEV'] end
During test driven development, we can get code reloading with CYPRESS_DEV=yes bin/test_server. On CI and when running tests locally, we omit the environment variable which leads to the default Rails test behaviour.