Investing in my future

Buying shares in the company I work for seemed like a safe way to start as an investor because I knew what I was buying. It felt entirely different from buying shares in a company I knew nothing about.  

I had not dared to start investing before this, because I felt that I didn’t know enough about it. I feared that I would invest badly and lose everything. Investment risks and their management were new to me, and I knew very little about investment products. I thought that investing was not my thing, because I’m not a particularly systematic person, or interested in the financial news in general.    

The share savings scheme for Gofore employees makes it easy to start investing. You didn’t have to understand everything about investing before buying shares. Since buying Gofore shares, I have started following the development of their value with great interest. This has also taught me more about investing. I wouldn’t have done that if I didn’t own shares in the company.  

I want to make Gofore a better workplace  

Share ownership has increased my commitment. I want the shares to increase in value and can affect the profitability of my investment through my own work. I want to make my work even better so that I will enjoy working there more and other employees will stay on as long as possible. Receiving supplementary shares after a certain number of years of service is a good added incentive.  

Share ownership also makes it easier to understand matters from the company’s viewpoint and to work harder to achieve common goals. Being able to contribute to value development both as an employee and owner has a major impact on motivation.  

Learning to be an investor through experimenting  

Owning shares in the company I work for has encouraged me to try my hand at investment elsewhere. I wanted to learn more: for example, I now know how to avoid the greatest risks and what kinds of returns I can reasonably expect. I follow my colleagues’ discussions on investing and ask more experienced colleagues for advice.  

I started investing only small sums, to practice at my own pace without taking big risks. I also tried to diversify my investments into different asset categories, such as funds and shares. In addition, I diversify my investments geographically to hedge against regional risks. Investing in shares requires time and dedication. I still have plenty to learn about these, but in the meantime, I plan to buy other shares as well.    

The threshold for starting out would surely have been higher if I had not bought shares in the company I work for. Now, I’m learning through experimentation. 

Maiju Kinnunen

Maiju works at Gofore as an expert in business and service design. Her passion is to support the resilience of organizations to change and to establish a culture of experimentation. Maiju has worked as a designer on large software development projects, as well as supporting organizational leadership in strategic decision making and change. She wants to build an empathic and liberal digital world, that supports people’s well-being and makes everyday life smoother.

Linkedin profile

Do you know a perfect match? Sharing is caring

WHO is piloting a world-wide secure data exchange.  Prime Minister of Estonia and World Health Organization (WHO) signed an agreement on 5th of October 2020 to start working on a digital immunization certificate and interoperability projects. The project includes implementation of X-Road and Gofore is one of the private companies that are willing to provide their help.

This project might initiate innovation beyond what has been possible! This might give a start to world-wide secure data exchange and unleash world-wide synergy to build stronger societies and solve new-era challenges.

Under the surface, it may look like something relevant only for techies, but this could not be further from the truth. These developments will change both our ways of working, and more importantly, how we think about and define trust. Trust is the core of every interaction and cooperation. It is important and needs attention. World-wide secure data exchange will teach us to trust the information that comes from a valid source through a secure channel.

Let’s imagine what this might mean for the citizens and the societies around the world!

If we could build trust between almost all organizations in the world, then it will have the potential of allowing us to overcome some of the biggest challenges of our time. It might help our societies push back against the polarisation and fake news, and to join our forces to achieve sustainable development goals when optimising for the world as a whole.

The most common fear is that the world-wide secure data exchange would enable a super database and an organisation with ultimate power? The reality is exactly the opposite. The solution will build grounds for a new way of collaboration, where the data will stay distributed and organisations will remain independent. We are building the foundation for a solution, where a third party could give the confirmation in a standardised way if the data is originated from a trusted source.

Where to start?

In an agile world, the first steps should be focused on tangible results in a short period of time, so we rapidly build, learn, and improve. We show-case a few potential services to be created. These help to explain the logic behind the solution we are creating together. We hope these also help you ideate and get started.

Vaccination passport check

In current times, we hope that we soon will see a reliable vaccine for COVID-19. We see governments struggling every day to make traveling restrictions as specific as possible and to avoid total lockdown. What if there would be a chance to easily prove if one is vaccinated or not. If the vaccine is reliable, then the ones who are vaccinated are not considered a health hazard. How to know if one is vaccinated or not? What if citizens would have a tool to prove that they have been vaccinated? What if you had a chance to confirm if the authority who made the vaccination is approved by WHO. Such checks could improve the life of both people who are vaccinated and the ones that are not. We would need to do less testing, which will make waiting periods for receiving access to testing faster. That could give us totally new opportunities for how to arrange and manage our lives in a post-COVID world.

Digitally verified proof for personal data

In everyday life, we often need to present data about ourselves. For example, giving evidence of my educational level in a job application, or while shopping, or proving to be a student or a senior citizen to receive discounts.
In such cases, the logic is the same. I present the data about myself. The question is, will a third party trust the integrity of the presented data. It is rather easy to make a A4 paper look like a certificate; especially when we have never heard of the institution that supposedly issued it.

Creating a system where all certificates could be validated becomes much easier if we can simplify the equation. In this new scenario, we can. We are building the foundation for a solution whereby a third party could issue the confirmation in a standardised and trustworthy way if the data has originated from a trusted source. Such validation would basically claim that “organization X exists and has issued document Y”, “organization X is authorized to issue this specific type of document”.

The desired mindset change in this scenario would be, that if you can trust the source, then you can trust the data. And did you notice that the third party will not receive direct access to my personal data. I will be empowered to present this information in a way that assures that I have not changed the facts. 

Right to represent

Imagine if you could check the representation rights of organisations online, free of charge. Why would you need to do it? It is common in the public sector and public procurements that the representation rights are properly checked. It is not so common in everyday B2B business, especially when the transaction amounts are rather small and the number of transactions is rather high. Does it mean that the private sector does not need to know their customers and cooperation partners on the same level of trust? Or is it because the risks of doing business with unknown parties are considered lower than the gains from the transaction?

From the implementation point of view, the best part of this service is that business registries around the world have that data already. Based on current best practices, names and birth dates do not require the consent of the data subject.

If you had the opportunity for potentially automated representation rights checking, free of charge, it would streamline doing business anywhere. If these types of checks become widely used, then it might become one of the strongest anti-terrorism or anti-money laundering tools.

These are just some of the first steps that would take us closer to a vision of building stronger and more trustworthy societies, together.

What is your dream, that we could make happen, together?!

Tuuli Pärenson

Linkedin profile

Do you know a perfect match? Sharing is caring

I had been working for Gofore for several years when the company was listed. I invested in Gofore out of pure interest when the employee share issue was launched – as an employee, I knew the company was developing well and I believed in its growth.  

I have also expanded my share portfolio by joining the staff share savings scheme. I am particularly interested in the supplementary shares issued to participants three years from the start of the scheme. During that period, it is easy to commit to Gofore.  

On the other hand, employee engagement depends on a number of other factors: interesting duties and customers, pleasant colleagues, and treating employees well.  

Interest in developing as an investor  

I am a long-term investor, investing only small sums. I already had experience in share and fund investments, and own shares in a company I used to work for. I only invest as much as I am prepared to lose.  

I think that owning shares in my employer company gives me a more objective view of it. This is possible because I’m already familiar with investing. As an employee, I view Gofore from a very personal angle: as part of the company’s daily operations, I know the business really well.  

As an investor, I can also view the company neutrally, which can be beneficial in daily situations at work. In this sense, shares in my employer are just some investments among others.   

I’ve also found it interesting to follow the share value’s development. I follow the workplace discussion on investment on Slack, and check the financial news in the paper.  

Next, I aim to expand my expertise in housing investment. I plan to read books on the subject to become more knowledgeable. Buying my first investment apartment is part of my five-year plan.  

Leena Virta-Niemi

Leena Virta-Niemi is an IT professional with long experience who has worked in many different organizations over the years. At Gofore, she has already held many different roles, currently primarily as a project manager and procurement expert, helping the client succeed in their projects. Leena is enthusiastic about customer assignments and cooperation with various customers.

Linkedin profile

Do you know a perfect match? Sharing is caring

Ethics and technology are ubiquitous, i.e. present everywhere. Ethical decision-making is a core aspect of IT consulting, but what does that mean in practice? I would argue that we constantly engage in ethical dialogue in everyday situations, little by little, or sometimes urgently. Such decisions often concern questions that no one can yet answer, but which need to be addressed immediately because the digital world never stops.

Artificial intelligence and social media are ideal subjects for ethical debate because they force us to confront the shortcomings of digitalisation. Many of the examples given are glaring, perhaps far-fetched. However, they also pave the way for broader and more down-to-earth reflection on how the digital world should function, on whose terms and for whose needs is it designed, and in which forums are the related issues addressed.

Whereas traditional power structures are only just adapting to the ethical challenges of the transition, we IT professionals must continuously solve such issues. The decisions we take affect the daily lives of millions of people via thousands of systems: such power should not be underestimated. Finns have exceptionally strong trust in the public sector and authorities. This trust is the result of long and systematic work, and as designers of public services, we must ensure that this well-earned trust is maintained, preferably even deepened.

Who will create the system used to process your data?

We are still living in the wild west of digitalisation, where data can be more or less freely sifted for gold. We are also beginning to develop a clear idea of how we do not want algorithms to work, and how we can do better ourselves. EU regulations and directives, national laws and organisations’ own strategies and policies are pointing the way to a set of shared ground rules. This does not eliminate the need for self-regulation by organisations, because ethical decisions are actually taken as and when needed:

  • We want to combine, analyse and visualise data collected from a range of sources. We cannot anonymise natural language automatically and reliably. Would it be harmful if we identified risks and declared them openly in our Privacy Policy?
  • Secondary use of health record data creates endless opportunities for product development. Do we really have to be scientific researchers to gain access to data?
  • The GDPR Privacy Shield procedure failed, and personal data can no longer be transferred to the USA. This makes many of the systems we use illegal in practice. What can we do?

The problem is crystallised when we encounter this sort of  challenges in everyday life: while technology advances at dizzying speed, we need time for ethical discussion. In addition, ethical discussion almost always requires multi-professional expertise and policies at top level, perhaps even globally. On the other hand, few Scrum ceremonies or project meetings are attended by people authorised to take these decisions within organisations.

Like systems, ethical solutions are based on iterations. Agile practices are no excuse for avoiding an ethical debate. In fact, they enable fast changes of direction, and lessons can be learned from any wrong decisions along the way. As challenges are identified, organisational, national and international structures are beginning to emerge for solving them. Precedents, initially thought to be individual cases, help in the progress of the overall process.

Ethics in the IT sector often concerns user rights, and service users are being consulted more often. For example, service design has brought end-users closer to service providers and developers, while the Web Accessibility Directive has improved the level of public services. Listening to the customer does not mean an extra price tag, but is a natural part of IT development.

Credits: Nawras Odda / Saut

The privilege of doing the right thing

Digital ethics sounds very high level, perhaps even intimidating. However, in addition to complying with laws and regulations, it is a question of making daily choices with the aim of doing the right thing: We can decide to formulate terms of use of services and privacy policies so that customers can easily understand their rights and what they are agreeing to. We can offer payable service versions to those who do not want to use services in exchange for their data. We can consciously formulate job ads to appeal to Muhammed and Mandy as much as Michael. We can ensure that AI is based only on training data which is a comprehensive sample of the subject and which we have permission to use. We can sleep soundly at night when we ensure that we act ethically.

However, current decision-making processes are subject to the risk of the wrong people having to make quick and sometimes wrong decisions to ensure that work gets done, perhaps without the knowledge, authority or budget needed to choose correctly. This is not a responsible process, or a pleasant one for the individuals concerned. Ethical responsibility should always be borne by organisations tasked with helping individuals to do the right thing. On the other hand, the discussion should not be confined to management teams and lawyers — it is important that all those who want to help build better digital services can do so to the best of their ability.

A toolbox could guide IT professionals in ethical decision-making

While numerous organisations have recently had to agree on common teleworking rules, the ethical basis for digital services should also be written up, to provide experts with practical tools for weighing up the right choices. Data strategies, data protection impact assessments, ethical guidelines, and agreements and requirements – as well as the rich discussion around individual cases — can support us in our work. At some point, the new practices and laws will become ‘hygiene’ issues, and in five years’ time we may no longer have to agonise about what web accessibility means, and how to guarantee it, in every project. The EU’s General Data Protection Regulation, which caused grey hair and sleepless nights at first, has already become part of everyday life.

Work has got off to a good start, but more tools and procedures are needed. Our aim at Gofore is ambitious: we want to be a forerunner of responsibility in our own industry and have. In order to genuinely work towards creating a better world, a lot of concrete action is needed. For example, in line with Gofore’s Good Growth concept, we are formulating metrics and methods to support sustainable growth, and the company’s first Code of Ethics was jointly created early in the year. Our ethical guidelines beautifully conclude what it is all about: how to be humane and to radiate goodness around us. Maybe what is done routinely can be sublime at the same time.

Kirsi Aantaa

Kirsi Aantaa works at Gofore as Service Architect and helps her customers especially with procurement. Kirsi is a humanist with a passion for designing smart, ethical, and value-creating digital services.

Do you know a perfect match? Sharing is caring

From passive to active investor

I had only been working for Gofore for a few months when I decided to join the staff share savings scheme and buy company shares at a discount. Investing was nothing new to me because I had started as soon as I turned 18.

I had viewed Gofore as an interesting prospect well before I became an employee. It was a nice coincidence that I took part in Gofore’s IPO in 2017. Even then, I viewed Gofore as a good investment, and I still own the shares I bought at the time.  

More active investor  

Previously, I would have described myself as a rather passive investor but, thanks to owning shares in Gofore, I’ve become more interested in the company’s press releases.  It’s easy to keep up with Gofore’s press releases, as the bot adds any new press releases to our internal discussion forum automatically. It’s great that we have a sense of community and open, active discussion channels on various subjects.  

I follow the development of Gofore and my other investments at least once a week, sometimes even daily. I read social media discussions, analysts’ reports, and online discussion forums. I also follow the Moneybags channel in Slack, used for Gofore’s internal communication, which features a range of investment and financial discussions among employees.  

A better understanding of the employer’s business  

It makes sense for me to own a part of my workplace and work towards developing it. My work motivation has always been high, and I’ve taken part in Gofore’s sales and marketing alongside my regular duties. For example, I’ve been interviewed for several newspapers about the development of our bots, and have written blogs for Gofore’s websites. I’ve also assisted the sales team in making offers.   

I want to help win more interesting projects – and euros – for the company. I would probably do the same even if I had not invested in Gofore, but now I have the added incentive of increasing the long-term value of my investment. I feel that a combination of ownership and employment has taught me more about the consultancy business and profitable growth.

Aapo Tanskanen

Aapo specializes in liberating people from dull knowledge work by connecting new technologies together to create holistic solutions. His core competencies are Chatbots, NLP, Data Science, Robotic Process Automation (RPA) and Knowledge Management. Aapo has been transforming employees’ work life by creating solutions like conversational chatbots and voice assistants for reporting working hours and buying train tickets.

Linkedin profile

Do you know a perfect match? Sharing is caring

The journey towards holistic management of phenomena, ecosystems and wellbeing has already begun. We have the tools, so now all we need is the courage to use them.

I already knew in the late 1990s when studying software production that artificial intelligence was going to change the world. Now, based on a Ph.D. in neural networks, 10 years of leadership experience, and recent developments, I can use AI to point the way towards beneficial growth for society.

While developing Gofore’s data-driven and AI business activities, I have a mission to discover how AI can help create a better world.

I believe that change begins with leadership. Yesterday’s strategies, metrics, and tools can only keep us where we are now. The problems with management lie in organisational and service-production structures, and the current management mindset. Traditional knowledge management tools, such as BI or data resources, will not necessarily lead to a change of approach: the data collected with them tends to reinforce old structures.

If it didn’t, we would be living in a somewhat different society.

Artificial intelligence is shaking up leadership

We’ve come a long way since neural networks were the playthings of scientists only. It may still be early days, but AI has already transformed management. The actual transformation began in 2015, as I was joining Gofore.

This was the beginning of a unique journey combining management, data and AI. We have noted that the availability of sufficient facts has a transformative effect on management. We can provide such facts by using AI and machine learning to create insights — based on existing data — which reveal anomalies in our current activities.

For example, I find it somewhat absurd that the work of medical doctors is still measured based on patient volumes. This ignores the actual value created by the doctor, i.e. the improvement in the patient’s wellbeing and health.

Despite drowning in data, we remain unable to manage the growth of wellbeing or its impacts!

Towards managing wellbeing and impacts

Fortunately, tools are available for this. It’s all about having the courage and willingness to use them while recalibrating management to shape the wellbeing of customers.

This is promoted by using data and AI to generate an overall picture of the customer’s situation.

For example, take work done on behalf of child welfare services in Espoo. Data analysis identified 280 variables that can be used to predict which young people are likely to become clients of child welfare services. Several dozen independent factors must probably be in place for the risks facing an individual to be realised. No one working with families can understand the combined effect of such an array of factors, and provide the right services at the right time. But hundreds of such factors are small fry for an algorithm.

This is state-of-the-art, as well as being a big deal! Service management can be unified by combining data, anonymously, from a range of fields. The same applies to the industry. A single institution’s data resources are rarely sufficient for understanding the customer’s big picture, but open data can already be used for this.

What comes next?

Looking even further ahead (which the researcher in me particularly loves to do), we see the age of data-driven platform ecosystems. In this era, management will become the management of ecosystems and wellbeing. The consumer will no longer have to be a ‘system integrator’, sifting through services by dozens of providers.

This too is being developed, for example via a service for solving the labor market mismatch problem. A CV is uploaded into a single system, where it is connected to a platform ecosystem and machine learning links it to all current vacancies. The path can be measured all the way up to employment. This is genuine match-making in working life (in Finnish): Tekoälyn hyödyntäminen ESCO-osaamisten haussa, Hyvä tekoäly – algoritmi, joka on suunniteltu auttamaan!

The Aurora AI project involves a similar issue. It envisions a system that provides people with services that fit their life situation, regardless of the party that is providing them. For example, a person moving to a new town will be offered topical services, from bus tickets to electricity contracts.

I am hugely inspired by the prospect of Finland being a forerunner in this. We have the necessary technical expertise, and the authorities have access to high-quality data. In addition, trust exists between citizens and the authorities. We have all the ingredients we need, we just need the courage to prepare it into something good.

I think Gofore is one of the few organisations in which my ideas resonate. It’s full of people like me, seeking opportunities to produce something which takes meaningfulness and impact to the next level — wellbeing!

Pasi Lehtimäki

Linkedin profileTwitter profile

Do you know a perfect match? Sharing is caring

Being the best possible workplace for our employees has been a core value of Gofore from the beginning. Our company has a strong culture of employee inclusion, which is also reflected in ownership. We have included employees in our financial success in a very tangible way.   

In fact, so many Gofore’s employees own shares in the company. Employee ownership is an important way of engaging employees. The benefits of ownership are realised as dividends and higher share value, although there is always a risk involved in terms of returns.  

Gofore has always been also flexible in employee remuneration, which is being continuously developed. Following a number of acquisitions, we have a wide range of remuneration practices and employee benefits but are unifying them, while making sure they fit every part of our organisation. Our guiding principle is to create remuneration systems that strengthen the culture we are aiming for. Competition is tough in recruiting the best people in our field, and attractive remuneration schemes can increase Gofore’s appeal as an employer.  

Rewarding employees is also a management method at Gofore, whereas share ownership encourages employees to develop the company’s operations through their work. As owners, we are all in the same boat, seeking to make Gofore a pioneer in the ethical, digital future. 

The biggest boost from the employee share issue  

Interest in ownership has been high from the start. The first Gofore employees bought shares in the company very early in its history. But the first major push came when the company was listed in 2017 – the personnel offering was oversubscribed 1.2-fold. Employees were attracted by the discount price of the shares. Subscribers were also included in a matching share scheme.  

We believe that offering shares help to engage new employees. In 2018, we organised an exceptional recruitment campaign, making new employees shareholders in our company by providing them with shares worth EUR 1,500 as they signed their employment contracts. The campaign attracted some of the best talents in the market to Gofore.   

In the same year, we launched the CrewShare share savings plan for our crew. Gofore employees can save part of their salaries and use it to buy Gofore shares at a reduced price. Participants are also entitled to matching shares once their ownership and employment have continued for long enough. There are currently three savings periods under the plan, and almost 260 participants.  

Ownership rewards and teaches  

Going the extra mile for themselves motivates many of our employee-owners in their daily work. When you own a slice of your workplace, you are committed in a new way to the company’s share development, and work seems more meaningful. Obviously, commitment to an employer is affected by many other key factors, such as opportunities for development, varied duties, pay, and an international working environment. That, at least, is how my list looks.    

Investing in Gofore has also made many employees interested in investment on a more general level. Owning shares in their employer may have been a safe first step into the world of investment for those who were unfamiliar with the risks, management, and various products associated with the investment. Being part of the share savings plan, for instance, has taught many first-time investors a great deal about saving and the principles of investing. Hopefully, this has also reduced some of their uncertainty about investing.  

Indeed, investing is an excellent way of developing yourself. I’ve been delighted to hear how my co-workers have talked about their plans to take the next step and look into index funds or housing investment. The threshold to begin investing would certainly have been higher without the buying of shares in Gofore – many have been encouraged to give investing a go.

Do you own shares of your employer company?

Nina Pavon

Nina Pavón is an experienced communications professional with a passion for continuous improvement. At Gofore, she manages investor communications. Prior to Gofore, Nina has worked as a communications consultant and an in-house communications specialist in a globally operating company.

Linkedin profileTwitter profile

Do you know a perfect match? Sharing is caring

Am I responsible developer?

First of all, I would like to ask you a question, what is it like to be a programmer in general not depending on the place or country (planet?) you live? The first answer that generally comes to my mind is a “person who writes code is a programmer”. But can your code be misused and cause more harm than good?

In my case, I start to think about this question after several occasions that happened in my life and I start to realize that it is more responsible and important than just to write code and achieve the given tasks by the management or a client. Don’t worry, I am going to describe below what happened and why I started to think about the stuff behind a code.

I hope to influence programmers to think about their code first and how it could affect others. If you in some way recognize yourself in the above text then stay tuned and be strong!

Can your code be misused?

At the start of my professional career, I didn’t think much about the repercussions my programming could cause. I was just happy and relieved to spend all my days’ coding and completing the tasks without actually thinking about what is behind my code or how it could affect other people later on? I always thought that there is no way to abuse or hurt someone through my code as I just completed the task I was told to do due to the deadline. Even if there would be any troubles I am not the one who is responsible for these, I just follow the orders. Actually, sometimes there’s no time to think about other things than just to complete your tasks on time because those could be so challenging that you could lose your sleep, which is absolutely terrible.

You should always analyze the given tasks and immediately express your feelings and doubts. Don’t feel shy or be afraid to ask ‘why?’ or say ‘no’. By using these words you insure yourself to make no harm to yourself or to your project. However, if you are just afraid to say these two words which are especially common among foreigners then you have to comply with not always reasonable goals and workloads of the client. In some specific cases, given tasks can violate the ethical rules and even harm someone and you will be the one person to take the burden and live with it. Could you live with it? If the answer is ‘no’ then it is time to act! Start to be an active part of the human community and take care of others as others will take care of you. Humans are social beings and we gather together into groups and communities as it’s our natural instinct. In that way, we are stronger!

Do not afraid to express your opinion and act

I didn’t act myself on time and I feel bad about it. I wish I had enough strength and strive to change it in my past working place with a terrible experience. It was 5 years ago and it was my first job in Finland and I faced the true injustice against me and other foreigners who worked there. I should say that my employer was also a foreigner. He used us to work for him twice cheaper and without medical insurance, unlike the Finnish citizens. It did not affect the working environment. I think it is because we were all passionate about the same thing as programming and did our job because we liked it, however, we all have bills to pay. In our case we have to earn enough to cover bills and be eligible to get a visa, otherwise, we will be kicked out of the country. Stressful, isn’t it? I would work there for a long time just to stay in this beautiful country.

The fear of losing my job drew me until I started to get to know more people and learn Finnish law. The natives shared their working experience with me and I shared mine in return and that is how I start to realize that something is wrong with my working place and the job I did. I realized that I should stop working there no matter what because I don’t want to support that employer and bring him benefits by exploiting me. I quit my job and applied to another job and of course, it took some time for me to start working at a new place and I stressed out, but I felt much better in a new working place and it was totally the right decision to change it. Don’t make the same mistake as I did and don’t let anyone exploit you and report immediately if this happens to you. You will find a better place if you are truly passionate about your work and if you’re a good specialist.

You should know that in Finland, all employees are protected by the unions and in case you have some troubles at work with your management crew, you should report to unions about any violations that happened to you at work. I hope I knew it from the beginning but it is better late than never.

Another thing I want to point out is even if you don’t face anything up above but your management asks you to do something inappropriate like collecting users’ data without their consent. You should refuse immediately because it’s a crime toward other humans. For example, big companies like Facebook and Twitter are famous for doing that, and if from first sight it seems these companies are great places to work at since they offer you a good salary and fun working environment but do not get fooled by it!

You should answer yourself if you work to help and protect others and what kind of impact are you creating? So when you are looking for a new working place you should explore the company’s background first (I mean not only the companies main web page because they know how to sell themselves) and then apply there if it suits you in ethical and other ways.

Current Situation

It is now literally everywhere and almost everyone now speaks about tolerance and ethics. The books about ethics are free to take on both floors of Gofore company. It is amazing! I believe that every person that respects his/herself will read it and will spread it among others.

However, I would like to talk not only about the Gofore community which is perfectly acquainted with ethic’s code but about people who work in other companies, about foreigners who found their first job and will do whatever it takes to keep it, about young people who are naive and blindly believe to the management and scared to lose their visa. The unions will protect you and moreover you could also apply to the unemployment benefits in case you are sick of the unethical behavior at your current job. Just take your time and improve your professional skills along with your portfolio but not spend your precious time working on the bad guys and getting the bad working experience. I have been there and honestly do not recommend it to anyone.

I would like to be honest with my current colleagues and help everyone to realize that if you are honest to yourself and to others you have nothing to worry about. Do not let ambitions blind you and always remember that all your actions lead to impact and making a positive impact is the best way to contribute to the community that you are living in.


I hope that this small blog post would help junior foreigner programmers not to be afraid of anything and do things that are right to do and not that you were told to. We are in 2020 and we have passed already a lot. We should learn from our mistakes and don’t get benefits from other people’s misfortunes. You now could answer yourself if you are an honest programmer and if it is something more for you than just the long lines of code and endless edits and tasks? Don’t trust anyone blindly. First, check then ask then make if else then don’t. I know it is obvious but forewarned is forearmed.

Always remember that we are creating products and services that will define the future.

Shokhrukh Yakubov

Shokhrukh Yakubov works as a Mobile Application Developer and Scrum Master at Gofore. He has experience working as an entrepreneur, consultant, and in-house software developer in different companies throughout Finland. Currently, his main focus and interests are React Native and Native Mobile Application Development.

Linkedin profile

Do you know a perfect match? Sharing is caring

Making an animated gif with PHP

I came across ttyrec file, a file that contains recorded Nethack-game. NetHack is an open-source single-player roguelike video game, first released in 1987. I wanted to make an animated gif out of it.

Image Source: Wikipedia

Previously I have interpretted a ttyrec-file into a 6415 different gifs.

I have a transformed a ttyrec-file into 6415 different gifs. How to make an animated gif out of those gifs? Here again there are ready tools, starting from ffmpeg, a command tool that is capable of doing many kinds of media files and transformations. Then again, I want to define the delays directly in code so that I can get the delays exactly the same as in the original ttyrec-file and possibly modify the delays too. I started with some googling. What are the options? Has someone already made this?

My limitations were that I wanted the tool to be done with PHP as the vt100-terminal interpretter was already done with that and I could package them to together. All I could find was a piece of code that was done 12 years ago. The code was also copied across the internet but the code looked pretty bad. It had no comments, the variables were non descriptive and there were few syntax errors and depricated use of brackets {} in it. After a while decided that I had no other options. Copied the code and started thinking what was happening there. After some debugging and fixing the syntax errors, I realized that the code builds the animated gif from existing gifs to a new gif with bitwise operations and at the end concatenating individual gifs into a single gif.

I realized that this programmer had made something brilliant and amazing but at the same time something undocumented and very difficult to understand.

I tried out the code and it worked. Refactoring comes next. But firstly, before anything else, I made a test to verify the functionality; just a script that creates an animated gif from a list of gifs. I could verify after each modification that the code still worked. After a bigger change, it is best to run it, so you can be sure that the code still works and you haven’t broken anything.

Then to refactoring. I started with the class variables

Looks ok. We have an array and some ints – no descriptive names. Skip this for now.

Then onward to the constructor.


We have a constructor with some checks. First we need to have $GIF_src and $GIF_dly as arrays otherwise we have an error “Does not support function for only one image!”. $this->COL is some sort of color. Also there is $GIF_mod that tells if the GIF_src is a list of filenames or a list of opened gifs as strings.

Let’s fix this

  • Choose descriptive variable names
  • PHP 7.4 has strict typing of variables; lets give types to variables.
  • Also I realized at some point that $GIF_LOP is an integer that tells how many times an animated gif loops. Rename that.
  • $GIF_DIS is disposal method of background color between frames and that can have four values defined in specs of gif.
    • Disposal Methods:
    • 000: Not specified – 0
    • 001: Do not dispose – 1
    • 010: Restore to BG color – 2
    • 011: Restore to previous – 3
  • So valid values are 0, 1, 2, 3. Rename and validate the value.
  • Notice that we don’t need to test anymore whether the variables are arrays or not because PHP will throw an error if they are not that type as they are typed.

Then continue with the constructor.

The $this->BUF has the gifs in a string array. The code also checks that the files are gifs and also that GIF89a gifs are not animated gifs. After checks in the constructor we add the gif header, add individual gifs, and lastly the gif footer is added.

Let’s fix this.

  • Make a separate function for constructing the actual gif. The idea is that the class contructor sets the variables and then we have a public function that actually does something.
  • We loop the gifs, opening them one by one. On the first round we add header and firstFrame that we need later. Then we add the frames and finally we add the footer.
  • Removed static method calls GIFEncoder::GIFAddHeader. Even the old code uses $this variables, so there’s nothing static about this.
  • When looking at loadGif function, I actually made the functionality worse. I don’t check if the gif is animated or not. I rely on the user not to send animated gifs to this class. So I’m going to rely on the programmer. The check can be done somewhere else if needed.

Then let’s check those helper-functions GIFAddHeader and GIFAddFooter.

What. Is. Happening. Here. Wikipedia to the rescue and particulary Wikipedia’s gif article. And the string “!\377\13NETSCAPE2.0\3\1” is a good clue. It took a few rounds of iteration to get this to the final state.

  1. Put the magical strings to constants – they don’t change
  2. Send the bitwise operations (<< & 0x07) to a named functions. So now we have isGCTPresent and getGCTlength functions.
  3. $cmap is actually length of color table, so name it correctly
  4. Haven’t actually tested what happens if function isGCTPresent returns false, we have no gif header, so most likely something fatal. Tough luck.
  5. Added comments. There is no way that this can be commented too much since there is not a lot of people who know how to encode a gif properly.

Then to a masterpiece of a function called GIFAddFrames. Adding a single gif to animated gif.

Scary looking stuff. Here we initialize some variables. $this->BUF has the gifs, so we do something with the first gif, presented here as $this->BUF[0] and the current frame $this->BUF[$i]. Also there is something magical in string index 10.

Let’s Fix this.

  • First we remove the firstFrame. Create a function that is called in the initial loop where we set some variables from the first frame and after that they are reusable for frame 1, 2, 3, 4, … n. So no need to extract these values in every loop.

Then the rest of the beginning of the function, we just rename variables and extract functions. Not the prettiest, but it will do.

Then continue with the function. There is more.

  • If the initialization of color is not set ($this->COL > -1) we have a check – we just set the color at the constructor and we have no need for that.
  • Then some sort of comparison and a switch case, where we compare the the first character of $Locals_tmp. The “,” is the beginning of image descriptor block, don’t know why the other one is there – just remove that and we get this

and the substrings at the end are image data and image descriptor.

A few more lines to go.

The $this->IMG > -1 is to check if this is the first frame and then three a rather similar blocks of code. The same can be achieved with a single if-else condition. If the global color table of a gif exists and the number of colors or the color table differ from each other, we need to add that, otherwise that is the same as the global and we ignore the local color table.

And that’s it. Refactored.

Then when I tried to run this with 6415 gifs I got an out of memory error. Bummer.

That was because the code builds a single string before outputting anything. So I needed to add some helpers for writing the gif.

Call the openFileForWriting at the beginning of gif creation, cleanBufferToFile in the for loop where we add the gifs and closeFileForWriting at the end. Cool. This helped with two things. The execution time went from 63 seconds and running out of memory to 4 seconds and writing successfully a 28 MB animated gif.

Image Source: Nethack server

The two parts of this project were different and both were very interesting in their own way. The interpreting of vt100-commands resulted in a clean new structure but some of the commands, like the backspace character, brought intriguing issues when building that. Debugging the terminal commands took time. For both cases, I had to research a lot of background knowledge from the specifications. The whole project took roughly 30 hours of coding, studying, and refactoring time.

The animated gif building part was a straightforward refactoring project. And that was fun. It took at least 10 iterations before I got the animated gif building into a shape that I wanted. The refactoring is nice, as you have a working code, so you always know if it’s working or not. If the code breaks, you can revert the part you have just changed. When building something new, you will encounter problems that haven’t been solved yet. The skill of refactoring and building something new is very important for a developer.

Making a VT100 command interpreter with PHP

Link to repository

Wikipedia GIF


Duukkis has been building the Internet for 20 years in multiple various size projects. He is a coder and maker of things. He has done over 70 Twitter-bots, a noun- and verb- conjugator with PHP, and a portrait from 7366 pieces of Lego. He is a developer, architect and a nice guy.

Linkedin profileTwitter profile

Do you know a perfect match? Sharing is caring

At one of our German customers, we support the maintenance and feature development of a long-standing web-application. In this application, many different roles interact with another to achieve the completion of a common goal – the maintenance and repair of giant, hangar filling industrial machines.

No doubt, for our tester in the team, this can be cumbersome. For testing many features she has to log in and logout many times in different roles, to assure the correctness of even small parts of the process. The login and logout progress unfortunately are not quick, as the application is hooked into a multi-layered corporate Single Sign-On process, involving an IoT-platform. Developers also (let’s face it) we sometimes take the short route and don’t test enough with every role when we should.

Automated testing is not available to the extent we want it, so manual testing takes its place. If this sounds familiar to your project then that’s what we can help you with.

Your first Chrome extension

Meet the Polyjuicer (full source code). Once installed, the Polyjuicer allows you to switch the currently active user in your browser without going through the steps of first logging out, looking up the correct test credentials, then logging in again. A project-specific problem perhaps, but surely not a unique one.

It builds on an authentication process well known these days in web-applications, where a user authenticates at an authority to receive a JSON Web Token (JWT) which is then sent together with every future request to the application server. The following drawing summarises this (industry standard) process:

The browser extension we are building together will hook into this process. Before we start there is one requirement that makes this whole adventure work:

Having that said, we can already put our extension into the grand schema. As one UML-schema says more than a thousand words we leave you with this:

Our Chrome extension boilerplate

Chrome extensions are written in JavaScript (JS), but we are leveraging the power of Typescript (TS) and then transpile and bundle it with the help of webpack. We will not be going into how this setup is done, but instead, accept it as boilerplate and focus on the extension’s specific mechanics. jQuery is used as a JS framework to do some of the more verbose lifting of JS and help achieve a more readable syntax.

You can find the boilerplate for the code in this repository on the init branch. Best check out the init branch and navigate to that directory now. You will find the following structure:

As the directory structure suggests, our extension can be divided into two main parts:

background and popup. This is due to the inherent nature of Chrome extensions.

  • The popup is the part the user interacts with. It is there for handling all the user interactions. For convenience reasons, we also place our credentials.json file in this directory. This file holds some fictitious credentials, following typing by the interfaces in the model subdirectory. Go there and get familiar with those interfaces. All our user interaction logic will be placed in the index.ts in the popup folder and we will also call most Chrome APIs from there. Unfortunately, not all Chromes extension APIs can be utilised through the popup scripts.
  • Some Chrome APIs can only be called by the background script. We will later get to why we need this, for now, we have an almost empty index.ts file in the background directory.

Background scripts, the popup, other metadata, and permissions are linked via the important manifest.json, a file we will see more of later and which we placed in the static subdirectory. This directory is holding some resources that are only barely altered and are not containing TS or JS. Both files will be continuously copied by webpack during the build process into the extensions root-directory.

Buckle up & start the engines

From here, we just need to start our continuous local build process. Run npm install and then npm run build:watch from the terminal to keep webpack constantly rebuilding your changes. You will notice a new dist directory appearing. To load the (yet unsuitable) Chrome extension navigate to chrome://extensions/ and activate developer mode and click on load unpacked. A new icon will appear in the list of your installed extensions, next to the browsers address bar. Just click on it to see the popup. You are good to go. Every change you do will automatically result in a new compilation. Pressing the update button in the extension menu is advised after each change. It’s a good suggestion to remove and re-add the extension when you experience old, unexpected behavior.

On checking console output

There are different ways of checking on console.log output, depending on which part of the extension we look at:

  • For the popup you can access Chrome’s developer console by first clicking on the extensions icon and then right click inside the appearing popup and choose “Inspect”.
  • On the background scripts there is a link for each installed extension you can click on chrome://extensions/ which will lead you to this separate inspection window.

The popup user interface

We already prepared all the HTML and UI JavaScript of the popup boilerplate for you. As everything else, you can see it is linked in the manifest.json, under the browser_action key. Take a look at popup/index.ts now to see how we load the credentials and register listeners. Interesting and unfinished here is the handleUserSwitch() which will be invoked when a user requests the switch action.

The next drawing outlines the steps we execute to achieve the full user switch. We will approach the problem in this order. In the process, we will have to query the authentication service, as well as Chromes Browser API for extensions.

For clean-code reasons, we are adding one additional layer, where we wrap Chrome’s API that works with callbacks into a promise resolving method. We do this step by step and for convenience reasons let a little bit of our logic get into it as well.

At first, we start by adding a new file and class to the popup directory.

Getting the current hostname and cookies

Let’s add our first code into our first new file. To get Chrome to tell us about the current tab’s hostname, we need to get the current tab from it. For this, we call to Chrome’s tabs API from our new static method.

We wrap this call into a promise which will resolve when a valid result is returned and to reject when unexpected behavior appears.

As you can see, we already try to extract the current tab’s hostname within this function, therefore muddying a little bit the waters of what a pure ChromeApiPromiseWrapper would suggest.

Now while we are at it, let’s add another function. The function getCookieByHostnameAndName() returns to us the first cookie to a matching hostname, filtered by its name. We resolve the promise if we find such a cookie and reject it if we find none.

Having those two functions ready, we can bring them together in a good promise fashion in a combining method within a new class, the UserSwitcher. We call the method getCurrentTabCookie() and it uses the Promise.then() functionality. As this method returns a promise itself, it is easy to reuse it in our main entry function to the UserSwitcher, the public execute().

Linking the button

Before we can continue with implementing the execute method, we want to be able to early test what we are doing. For that, we need to link the button with the execute function.

Switching our authentication cookie

We continue by changing the content of the discovered cookie with a new value, the value we receive from the authentication service (called via TokenProvider). We must update our execute method in the UserSwitcher to call this new method.

It becomes clear that we need two more wrappers in our ChromeApiPromiseWrapper:

  • removeOneCookieByNameAndUrl()
  • setOneCookie()

And also the TokenProvider. That will come a bit later.

A couple of things are noteworthy in these new methods. At first our two new public functions all never reject their promise. This is simply because, at the time of writing this, Chromes API simply gives no feedback if the action was successful or not.

Also, you will notice that our new cookie uses most values from the old cookie, including the expiration date. For the context of this extension, this is an acceptable simplification.

At last the additional function urlFromCookie. This is creating a url from the old cookie’s data, which is needed as new cookies are saved with the URL-information, but when queried they do not return this parameter.

Also, we can see one specialty: Cookies that are valid for an entire subdomain start with a dot “.” but are not accepted like that by Chrome (e.g. “”). We, therefore, strip it of the leading dot.

This problem actually applies also for our previous function getCookieByHostnameAndName() in a slightly different form. We can revisit and add it like this:

Now, if you try out the changes, you will see that they will not work. That is no surprise – but by design. To make this work, you first need to give our Chrome extension additional permission. All permissions are requested from the manifest file. Here it is, the permission “cookies”. The permission-section should now look like this:

The next thing missing is a new class, which acts as a service to retrieve our JWT from the authentication service. We have heard before from this, it is the TokenProvider.

Getting the JWT from AuthService

For receiving the new JWT we create a new file TokenProvider.ts. The following implementation is obviously highly dependent on the service your project has available. We use a jQuery ajax request to send a formatted JSON to the service. The request can be adapted to your project’s needs by changing the data attribute. Luckily for us, our IUser interface matches exactly the serialized JSON request the service expects. The request’s result matches exactly the AuthServiceResponse so we wrap our jQuery callback function into a Promise.resolve call and reject whenever there occurs an error.

Delete the session cookie

The last thing we want to do is to ensure that our application does not mix-up the new authentication data with stored session data. If this is not a problem for your context, you can skip this part. But for our client, we decided that this is a reasonable precaution step to avoid holding conflicting session data. The solution is easy and pragmatic: we just delete the session cookie. The application’s web-server will just instantiate a new session for us and it will be legacy free from our previous login. For this, we add the last functionality to our execute method in the UserSwitcher.ts. As it happens, we already have created that functionality, it’s the function: removeOneCookieByNameAndUrl(). Our execute function can therefore be updated to this:

Have you tested it yet? If not go test it and let the purposefully added console.logs guide you a little bit through the process or find possible errors.

CORS and background scripts

In our project we faced the problem that the authentication service did not send permissive CORS headers, therefore making it impossible to receive data via the TokenProvider. If you have the same problem (you will notice if that is the case) and you have no way of convincing the maintainers of the service to add some less restrictive CORS headers to their service, then there is not a lot you can do but deceive your Chrome into ignoring CORS altogether.

This is where the background service finally comes into play. For this at first, we need to extend our permissions in the manifest.json for the following two entries:

Without these entries, Chrome can not give us access to parts of its API. Then we add content to the already existing init() function in src/background/index.ts. The CORS_PERMISSION_SCOPE is fixed and can be looked up in the Chrome Api. We add a listener that is called with the result of any web-request, only limited by CORS_HOST_FILTER. This function then adds a certain CORS header to the received response, allowing us to trick Chrome into believing CORS policies have been sent by the service in our favor. Suddenly the authentication service is not restrictive at all.

That is the entire Chrome extension. Make sure to update all environment variables and the manifest.json to match your project. From there you are good to go!

Final notes

Firefox compatibility

Chrome’s extension API is very similar to the one of Firefox, so there should be no major problem to modify your extension to work also with Firefox. The main difference is that Firefox works already with promises while Chrome is still working with callbacks. Additionally, check the incompatibilities pointed out by the Firefox team.


If you have any problems, check if the correct permissions and URLs are added to the manifest.json. Generally, Chrome’s inspector is of great help understanding the inner workings of the extension. When having problems with deceiving CORS, remember that Chrome’s code inspector is called from chrome://extensions page per extension. And it is always good advice to refer to Chrome APIs for breaking changes or other updates that might have happened since the release of this article.


We have successfully implemented a Chrome extension that supports our customer’s development and testing process. This highly convenient extension in our project is in use by many team-members every day. Your project might have different requirements, such as sending the JWT via a dedicated authentication header or accessing the authentication service with different technology. Based on this tutorial you should be able to adapt your version of the Polyjuicer to those requirements.

Check Gofore’s GitHub account and navigate to the repository to get the entire source code.

Are you interested in working with similar technology in modern teams and on interesting projects? Check out our open positions in an office near you!

Achim works as a Senior Full Stack Software Developer at Gofore in Madrid. He has a background in Computer Science in Media as well as Human-Computer Interaction. As a software craftsman at heart and a passionate agile advocate, he supports our clients in the field of web-development, architecture, cloud, and test-automation.

Linkedin profile

Do you know a perfect match? Sharing is caring