A few gotchas for the Magento 2 product import

Six-seven years ago when I started with Magento, the import feature was lacking. While it improved, it still has quite a few issues even today. Mostly every import task I worked on was delayed due to unexpected core bugs. Extensions that promise to help with this come with their own set of issues. There is hope with the https://github.com/magento-engcom/import-export-improvements project, but till that’s done we have to get by.

First, the imports do not have a programmatic interface you can hook into, i.e. pass an array with data and get it imported. Luckly, Firegento fixed this with https://github.com/firegento/FireGento_FastSimpleImport2 . The module is just a simple wrapper over the standard import, so not many chances to break. Of course there is the standard Magento 2 product API, but it’s pretty useless for anything else than a few products due to slowness.

The second thing I ran into is that tier price imports are a special entity, i.e. you first import the product data in a format, then import the tier pricing in a totally different one. This is not what a merchant would expect and sadly, not even the Firegento extension has a programmatic interface for tiers.

Then another gotcha is that importing empty values does nothing by default. So if you set a product color, then decide to unset it by importing an empty value, it will still keep the same value as before. Similarly, if you import category associations and want to remove an older association, you are out of luck, the old link remains. This is almost a “feature” in Magento – https://github.com/magento/magento2/issues/7930 . The proposed fix is to use the “Replace” behaviour of imports, but that creates another issue – with “Replace”, product data is wiped out and recreated. Not something you want todo if you care about stats/old orders since all the product IDs will change.

Another nuisance is that all custom attributes need to be crammed in a single csv field like:

adhesive=,application=,application_description=,available_lengths=,available_widths=,color_group=,colors=,durability=,item_size=,part_name=,print_compatibility=,product_tagline=,release_liner=,thicknes=

 

For most of my clients, additional attributes is where the bulk of the data lives, so having them formatted as above is clunky.

For the good parts, the import is pretty fast, it can import images correctly and once you get the format right, most of the stuff works.

The conclusion? If you’re working on a import task, pad your estimates substantially, you will need the time to go through a various set of quirks you never thought of. By the way, all of the above refers strictly to the simple products, other product types might come with their own set of problems.

Choosing a programming language and why is PHP still relevant in 2018

Ten years ago, PHP was definitely the better choice for the web. Things seem to have changed though. As a new developer, you are faced with quite a few options. First, there is Javascript that can now be used both in the frontend and backend. Then, there is Python which has seen a huge momentum. Ruby has always had his steady share. And there are many other languages coming out everyday. The junior programmer is left wondering what language should they learn as a web developer.

First, the question of what programming language to learn/use is a lot less relevant than a junior developer would think. The hard things in programming are organising your code, naming your variables, getting into the OOP/functional mindset, not repeating yourself and creating simple solutions. None of these are programming-language dependent. Once you get a hold of those, learning a new programming language only means getting over the nuisance of getting used to the syntax.

So how does one choose a programming language for a specific task? In some cases, the choice has already been made and you have to continue using the same language as you are not starting the project, but continuing it. In others, the client simply prefers a specific language because they worked with it in the past. But let’s assume total freedom of choice.

Programming languages by default offer very small building blocks, like if, for, while constructors. Then they offer libraries with small, contained objects and methods to work with things like files and databases. While usually they are very far away from what you have to build, the building blocks are small enough so with enough work, you can combine them to achieve any kind of result. Actually programming languages can be splitted into two different categories:

  • general languages, like PHP, Python, Javascript. They are not trying to solve a specific problem, but give you the tools to solve any problem. With enough work, that is.
  • domain-specific languages. While you cannot do anything you want with them, they can help you solve a problem in a specific domain much faster. For example, SQL helps you create databases, then query for data in a very efficient way. Mathcad helps solving math problems. HTML is a declarative language that helps you format web pages. CSS gives you a good way to style them.

You usually find yourself needing to use at least one general programming language, along with a number of domain specific ones. As a web developer, you will probably have to use HTML, CSS, SQL along with your general language programming of choice.

When it comes to general programming languages, you care mostly about what exists out there than can match the needs of what you want to build. I tend to categorize “what’s out there” in three distinct areas:

  • libraries. Code that allows you to use new methods and objects, without imposing a structure. For example, a statistics library will give you pre-built methods to calculate averages, means, deviations etc. You don’t need any specific code style to use them. Just search the documentation for what functions/objects are defined and call them in your code.
  • frameworks. They are more about helping you have a sane structure for your code. For example, a web framework will probably force you to use MVC, organise your files in a specific way, be mindful about security etc. They are invaluable for the beginner as you don’t have to go through the huge exercise of finding the best way to organise your code. They are great for seniors too, as they provide a very well documented way of working which helps board new team members faster, or even hire people with experience on the same framework, if popular enough.
  • full solutions. Think WordPress. You install it, then you have a full, working blog. You can use it as-is, or start making changes to suit your needs.

Given the above, the smart choice is to use the programming language that has most pre-built components for your needs. For example, it’s almost a no-brainer that if you are doing machine learning, Python or R are the better choice. That’s not really related to programming languages, but to the fact that Python has the most diverse, production grade libraries related to data analysis and machine learning.

Luckily enough, most languages do have frameworks. Once you’re done with learning the basic syntax, spend some time in learning the most popular/suitable framework for your needs. See how it feels.

This brings me to the last feature, full solutions, and slowly to the point why PHP still matters. Most problems are not that unique in the programming world. For example, I have been making a living in the last 10 years by mostly building e-commerce stores. While each store is unique, there is a lot that is common to all of them. So then it only feels natural to ask the question whether you can start from a “base” e-commerce store and build from there. And of course you can. And here is where PHP shines.

Mostly because PHP is almost as old as the modern web, there are a lot of full production grade solutions built with it. For example, most of the popular open source e-commerce solutions (Magento, Open Cart, Presta), are built in PHP. Then there is the hugely popular WordPress on which you can build a blog or any presentation/content site really. If WordPress looks like too restrictive to manage your content site, then there is always Drupal. Now since e-commerce and content sites cover maybe 80% of the sites that are out there, that’s a huge part. And of course, there are solutions for forums, mail clients, database admins and many others, but they don’t seem like the kind of things one would build nowadays.

Given that with PHP, you have pre-built solutions, it only makes sense to use them when the requirements match. There are a few arguments against it that I will try to defer….

  • “I can build a blog from scratch in X hours/days”. Yeah, “a blog”. But you definitely cannot build WordPress, with all the flexibility it offers.
  • Popular software like WordPress or Magento have a huge marketplace aroud them. You can buy a jaw-dropping theme for WordPress to have a great design for a few dollars. You can buy integrations with your preffered payment gateway for Magento at a small fraction of the cost to build it. Try that with your custom solution.
  • You can add more people to the team by simply searching for people with experience on the platform, very low learning curve.
  • “But I organise my code better, make it faster, more readable”. Most of the time this is simply not true. But even if it is, an effort a few orders of magnitude higher rarely makes sense business-wise.
  • “But Amazon, Facebook, Google, [Insert big brand here] do not use a pre-built solution”. This is totally correct. There is a point when maybe it makes sense to move to a custom solution. But that should be done when you are able to have a team of top-level developers and a huge budget. Trying to prototype a solution with not enough time and a team of juniors will end up in a disaster. Also keep in mind that some of the solutions used by the big companies are custom just because they started that way and never made the switch.

Overall, I feel comfortable with PHP as I can use software like Magento and WordPress to kick-start my efforts. It’s a no-brainer for me to use those when requirements match. What about custom solutions? I still prefer PHP. As I was stating in the beginning,  good software is about organising the code correctly. I can do this in PHP as well as I could do it in other languages. I can also use a decent framework (preferring Laravel) as well as any other. But I am faster with PHP and Laravel as I have used them for years, so I am lazy enough to not switch to something else just do implement the same thing differently. The only valid reason for which I use another language is when that language offers a great deal of libraries to help with the problem at hand, libraries that are missing/are inferior in PHP. And in that case, I only need to get over the syntax errors and language quirks. Most programming languages are similar anyway.

Using a composer library in Magento 1, the quick way

Today I had to generate native XLS files from Magento 1. The https://github.com/PHPOffice/PhpSpreadsheet is the best library for the job, but it’s modern in that it uses composer and PSR. Since I really wanted to use this specific package, here is a quick way to include it in the now dated Magento 1 codebase:

First, create an empty directory where the library will be kept:

 

mkdir lib/PhpSpreadsheet
cd PhpSpreadsheet

Then, create a composer.json file:

#lib/PhpSpreadsheet/composer.json
{
  "require": {
    "phpoffice/phpspreadsheet": "~1.3"
  }
}

Then, still in lib/PhpSpreadsheet, let composer download the needed files:

composer install

To actually use the library, we will have to tell Magento how to include the directory in the path and also require the generated composer autoloader. In your helper/model/controller, add a init method to do just that:

protected function initPhpSpreadSheetLib() {
  //Add library directory to include path
  set_include_path(get_include_path() . PATH_SEPARATOR . Mage::getBaseDir('lib') . DS . 'PhpSpreadsheet' . DS . 'vendor');
  //Include composer autoloader
  require_once(Mage::getBaseDir('lib') . DS . 'PhpSpreadsheet' . DS . 'vendor' . DS . 'autoload.php');
}

Then, use the lib. Remember to use fully qualified class names as Magento is not namespace-aware:

$this->initPhpSpreadSheetLib();
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->fromArray($data,null,'A1');
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->save($tmpFileName);

Probably there are a million other better ways to achieve the same thing, but this looks like a quick solution to use a library without tinkering with the project’s structure too much.

Three questions to ask a prospect as a freelancer

When discussing with a prospect, out of respect for their time, you should find out quickly whether you can really work together. After a few long negotiations with clients, I came up with a list of three questions I ask upfront to make sure the partnership is a good fit.

What is your estimated monthly budget for development?

As a freelancer, you have multiple clients. I have found out that by myself, I can handle about 5 of them. Each client will have urgent needs, Black Friday is in the same day for everyone, each needs meetings for time to time. Because of this reason, aim for clients that budget at least 20% of your desired monthly income. Less than that is too much noise and you won’t be able to serve them well.

What’s your revenue (or number of orders/paid subscribers/paid downloads)?

Each client pays you out of their revenue. If they don’t make money, they won’t be able to pay you long term. No matter how well you do your job, they will not afford you at some point. Basically, a client will take a loss of profit only if:

  • They are a startup and hope that their product will sell a lot when ready
  • They have other sources of revenue (i.e. an online shop that’s backed up by a brick and mortar store)
  • They are heavily investing hoping to increase the business
  • They have no idea what they are doing

Evaluate well. While making some extra money is ok, it is better to have partnerships with profitable businesses.

Do you work hourly or fixed bid?

Personally I found out that working hourly is the best for my clients. If they agree on this, I simply provide my hourly rate upfront. With new clients however, you sometimes have to earn trust so you might have to go fixed bid for a while. To make sure that your expectations are aligned, give some examples from the past, i.e. “I have built this payment method integration for X”. The client will quickly realise whether you are a match for them.

Isn’t this to blunt?

No. As I stated in the beginning, you should make sure the basic terms are in order as soon as possible out of respect for the client’s time. There are some clients (especially in the lower tier level), that will wonder why do you ask these questions. Personally, I give them the same reasons I have outlined here.

What other challenges are there?

Even with the above questions answered and agreed upon, there are still challenges that might appear after signing the contract…

  • They might pay late or not at all
  • They always have urgent needs
  • In case you signed up for a fixed bid, they might ask for a lot of quotes and meetings, ending up by implementing very little, making most of your time unbillable
  •  You simply cannot communicate well with them

I was not able to find the right questions for the above, so my approach is to start with a “probation” period, in which both me and the client can part ways without much heads-up. With the probation set up-front (and possibly a lower rate if it happens), you will never have an unhappy client even if you stop the collaboration. Usually, a broken partnership is reciprocal, they will want to get out of it as much as you do.

 

 

 

Why hourly contracts are better than fixed prices

A while ago I have decided to charge hourly. This sometimes puts clients off, who seem to prefer the comfort of knowing the full project price upfront. However, fixed price rarely ends up well for me or for my clients.

Disadvantages as a service provider

  • Estimating is hard. Every project is unique. I either go too low and lose money or go too high and rip off the client.
  • Estimating properly takes time. I might need to spend weeks to architect a project. And I might need the client’s involvement to answer a lot of questions. Most clients do not expect this.
  • With a fixed price, two new challenges appear – time management (since fixed bid is usually fixed time) and scope creep (you want to make sure you build only what you quoted). Both things take time and a different skillset.
  • It’s hard to keep the client happy. Scope creep tends to be natural.  Most people cannot really understand the software completely till they see it. So since the client won’t be able to articulate the needs in the first place, they won’t be getting a fixed price anyway, unless you want to eat up the costs.
  • Working in teams make fixed price even harder. Winning a contract takes time. It is not uncommon that the original estimate was created by another developer(s) than the ones ending up doing the work. I have a very vague idea on how long it takes me to do something. I have no idea how long it will take for a developer that may not even be hired in the company when I’m estimating.
  • Fixed price is toxic for the team. It’s the number one reason for overtime, arguments, endless meetings, loss of profits.
  • In companies, fixed price adds a lot of overhead. Before you know it, you will need project managers to keep track of hours and progress. You will need client-facing persons to explain why something is out of scope. You will be writing a lot of proposals/change requests. You will have a lot of meetings to keep everyone in sync.

Disadvantages as a client

Clients usually think that fixed price is better for them. But here is why it isn’t….

  • The fixed price is a lot higher. That’s because any company will add risk and the cost of the additional staff (client partner, management etc). That easily multiples the price by a factory of two or three.
  • Fixed price makes the project lower quality. The focus is to finish as fast as possible.
  • As a client, you rarely know exactly what you want. Actually, it’s usually recommended to ask the specialist’s opinion along the way. So then why be forced to take all the decisions before starting the project?
  • The relation with the developer can easily turn sour. The worst projects are the ones that switched several teams of developers.

How can it work?

Of course, there are cases where fixed price works great, otherwise the model would have disappeared long time ago…

  • You can charge a huge price. That’s the case with the top-tier companies. Their reputation allows them to change so much that the development cost does not matter. Then they can hire/fire/switch teams so that they hit the launch dates.
  • You had the same project before. If you can just copy-paste most of the code, it would be silly to charge hourly. You might be able to deliver a 1000-hours project in 2-3 hours!
  • Project is small. This usually works for projects like logos or WordPress sites. If the project is just a few hours/days of work, it might be worth the risk. You will occasionally hit a picky client, but that may mean only 1-2 more days of work and can even out with the other projects.
  • You get lucky. Sometimes, tasks might take less than estimated. Since the client is in a fixed bid contract, you get to keep the extra money.

How can I charge hourly?

A lot of freelancers/companies will not charge hourly simply because they won’t find the clients to accept this. Here are a few tips to get paid hourly…

  • Get hired. Yep, that’s the easiest. A salary is hourly payment. While you might have a boss that asks you to work faster, you will get paid even if your estimates are wrong. Get more experience under your belt, at some point you will be ready to consult/freelance/start your own company.
  • Don’t reach out. If you have to actively search for clients, you’re doing it wrong. Hourly contracts imply trust. If a client reaches out to you, it means they already trust you to a degree. This applies to freelancers, I guess if you have a company with a sales team you should let them sell.
  • Learn the principles of Agile. Hourly works great with Agile. Build a process, present it to the client. Most clients initially refuse the approach just because they don’t understand how it can work.
  • Build trust. You might need to do the first project fixed bid, or provide a very accurate estimate. The second one will be hourly for sure if the client is happy. If the client has a solid business, they will always have work for you. So get a few of those and you’re good.
  • Associate yourself with bigger names. Be part of freelancer networks or collaborate with companies. Especially if you’re living in poorer countries, having a bigger company to back you up will give clients a trust boost. Not to mention that such networks/companies usually bring clients to you without any effort. Just tell them you’re working hourly and let them figure out the clients that want your services.

US continental shipping and Magento

A lot of websites in the US offer free ground shipping nowadays. However, most restrict to US continental. State-wise, this means all states except for Alaska an Hawaii. However, the US has a lot of protectorates that do not qualify as continental: American Samoa, all the “Armed Forces”, Micronesia, Guam, Marshall Islands, Mariana Islands, Palau, Puerto Rico, Virgin Islands.

That’s one way to look at it. The other is looking at the zip codes that are not qualified for free shipping. It looks like the continental USA is:

  • between 00900 and 96200 OR
  • between 97000 and 99500

Putting all this together as a set of conditions for a Magento shopping cart rule:

Screen Shot 2018-05-11 at 12.02.13

If you’re using Magento 1, here is the string you can paste in the salesrule table, conditions_serialized field:

 

a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:18:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:10:"country_id";s:8:"operator";s:2:"==";s:5:"value";s:2:"US";s:18:"is_value_processed";b:0;}i:1;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"2";s:18:"is_value_processed";b:0;}i:2;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"21";s:18:"is_value_processed";b:0;}i:3;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"3";s:18:"is_value_processed";b:0;}i:4;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"6";s:18:"is_value_processed";b:0;}i:5;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"7";s:18:"is_value_processed";b:0;}i:6;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"8";s:18:"is_value_processed";b:0;}i:7;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:1:"9";s:18:"is_value_processed";b:0;}i:8;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"10";s:18:"is_value_processed";b:0;}i:9;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"11";s:18:"is_value_processed";b:0;}i:10;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"17";s:18:"is_value_processed";b:0;}i:11;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"20";s:18:"is_value_processed";b:0;}i:12;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"30";s:18:"is_value_processed";b:0;}i:13;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"46";s:18:"is_value_processed";b:0;}i:14;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"50";s:18:"is_value_processed";b:0;}i:15;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"52";s:18:"is_value_processed";b:0;}i:16;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:9:"region_id";s:8:"operator";s:2:"!=";s:5:"value";s:2:"60";s:18:"is_value_processed";b:0;}i:17;a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"any";s:10:"conditions";a:2:{i:0;a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:2:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:8:"postcode";s:8:"operator";s:1:">";s:5:"value";s:5:"00900";s:18:"is_value_processed";b:0;}i:1;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:8:"postcode";s:8:"operator";s:1:"<";s:5:"value";s:5:"96200";s:18:"is_value_processed";b:0;}}}i:1;a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:2:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:8:"postcode";s:8:"operator";s:2:">=";s:5:"value";s:5:"97000";s:18:"is_value_processed";b:0;}i:1;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:8:"postcode";s:8:"operator";s:1:"<";s:5:"value";s:5:"99500";s:18:"is_value_processed";b:0;}}}}}}}

 

I’m guessing all this changes and may not even be 100% accurate, but it’s the best I could find as far as “free continental shipping” goes.

State of remote working in 2018

I am working remotely for more than 5 years now and I hope I will continue doing so. My personal opinion is that remote work opportunities are stronger than ever. I compiled together a list of sources which I believe can land you remote gigs.

But first, a few assumptions…

  • The below refer to remote work opportunities for developers. I am not aware of the market for other specialisations.
  • I am assuming you are a senior developer and have skills that are somewhat in demand.
  • I considered sources that can get you to at least $50k a year, i.e. a decent living in most countries. But usually under $100k. It’s pretty hard to go over this if you are working remotely.

Upwork

https://www.upwork.com/ is probably the largest freelancer market in the world. It’s a jungle. 95% of the clients have unrealistic expectations. If you post a project, you get hundreds of applicants in minutes, most of them being fake profiles, accepting any conditions you ask for just so you award them the job.

However, if you manage to get over all the noise, you can land some well paid and interesting jobs. On top of that, anyone can join Upwork. Activate your account, put up a good looking profile and you’re good to go.

Here are a few tips to be efficient on Upwork

  • Do not bother with general job applications, search for the specific combination of skills that you have (i.e. Magento + WordPress + SEO). Once in a while, a client will need exactly that, you will be an awesome fit. Any Upwork search can be saved as a RSS feed, do so and wait for the jobs to come to you.
  • To get reputation, snipe for “Urgent” jobs, i.e. set your RSS feeds to “Urgent Magento”. There are a few number of users that break their sites and will take on the first developer that applies to the job. This assumes you are available to work right away. And most of the time, it implies only a few hours of work. Definitely not worth the money, but can help build up reputation quickly.

Even with a good reputation, you will still spend a lot of unbillable time searching for jobs. I’d advice to leave Upwork as the last resort to get work, but consider it nevertheless.

TopTal

https://www.toptal.com/ is a nice surprise. Similar to Upwork, they are a project/job market. However, they are curated. First, you have to go through a pretty hard interview process to get admitted. Then, they do the same with the clients. You will not find any “I need a website built for $100” requests on TopTal.

Then, TopTal only works hourly. Not sure about you, but I suck at estimates. 9 cases out of 10 I lose money in a fixed bid, so being able to work on hourly engagements is the best for me.

The best thing about them is that they have recruiters. Most of the time, a recruiter will ping you about a job that was posted and fits your skills. While you can definitely apply to jobs yourself, you can also sit tight and wait for the recruiters to find good matches for you.

They also try to build a community, there are a lot of events, both online and offline that can really help you grow professionally.

Crossover

https://www.crossover.com/ only does full-time jobs, so it is a bit different from the above. They also have pretty hard interview process. As a twist, they organise “hiring tournaments” in which you go, spend the day working on some challenges and can go home with a job.

They exaggerate a bit in that when they say a job is paid 200k per year, they actually mean you get the amount if you log 8h/day, which would mean at least 10-11 hours spent in office. And that you never take a vacation. So a job with them is probably paid 30% less than advertised, but that’s still a pretty sweet deal!

While I never worked with them directly, I heard from first-hand acquaintances that you get hired in a few weeks after passing the interview.

X-Team

https://x-team.com/ – similar to Crossover, they only offer full time jobs. You sign up with them and get to work as an addition to an existing dev team. Their interview is easier, in that you can showcase existing code instead of writing something new. If you get accepted, you tell them your rate, skills and desired start date and they will find something for you.

I never worked for them since I am not looking into a full-time job, but they contacted me a few times with opportunities so they look like an active community.

Stack Overflow

This is pretty simple – https://stackoverflow.com/jobs/remote-developer-jobs . Watch this list, apply to jobs that fit your skills.

LinkedIn

LinkedIn is usually fit for full-time in-office jobs. However, there are a few tricks here…

  • Add the word “freelancer” to your profile.
  • Make sure your profile emphasises your technical skills. Things like “I helped the company grow 10 times bigger” are good for corporations/non-dev roles.
  • Be prepared to get a lot of offers that are not remote. Responding with “Thanks, but I am not interested in an office job” is not too hard.
  • Wait. At some point you may get a remote opportunity. Personally I got a few clients form LinkedIn.

Direct

Know the companies that work remotely. GitHub, Automatic, Mozilla are just a few names that hire remotely. Get to know the ones that match your skill set. Watch their job listings. Get hired.

ROM Hacking – Battletoads

One of my preferred games as a kid was the NES version of Battletoads.  NES games are hard, but Battletoads was almost impossible. I remember I got pretty good at it, managed to get to level 10 or so. I thought I’d give it another chance, but this time over, I did not manage to get over level three. Since I barely have the time or the will to replay a game hundreds of times, I decided to get into ROM hacking, see if I can make my own cheats and finish the game.

While there are many emulators out there, it seems that the best tool if you are into ROM hacking/modding is http://www.fceux.com/ . The nice twist is that the emulator can load Lua scripts that allow you to manipulate the game. You launch Fceux (via wine if not a Windows user), load the ROM and load your scripts. My “IDE” for the day looks like this:

Our dev env....png

Now, for the “Hello World” script:

while true do
 emu.message('Hello World!') 
 emu.frameadvance() 
end

The principle is pretty simple. The script is a while loop. You add your code, then call emu.frameadvance() to pass control to the emulator and render the next frame. The code above simply displays “Hello World” on the screen all the time:

hello-world

Let’s do something interesting. ROM hacking is about finding where in the memory a value is stored (i.e. number of lifes)  and changing it. Here is someone hacking Mario:

8nnzb_feir-jw_drgzdj_ir9vntk4rrpdjjzlbidrx2lmw1bng-ktcw_kedilyqmrdfdfptswbddyefak8whnfa8xdgwzcsgymvs8rgszi7cg6n_anvcp0j6mjznjpzgv1cy4m

This guy makes it look easy. The truth is that you can spend countless hours trying to look for a certain value. In the end, you have a memory address that you can change. For Battletoads, I got a bit lucky as someone already found some useful addresses – http://www.thealmightyguru.com/Games/Hacking/Wiki/index.php?title=Battletoads

So, to add infinite lives, it looks like I need to put in 05 in the 0011 address. My Lua cheat can simply be:

memory.writebyte(0x0011, 0x05)

That might work for a normal game, but Battletoads is incredibly hard. Having infinite lives is not enough. In most levels, when you die you restart from a checkpoint, having to redo part of the level, which can be very frustrating.

Another cheat caught my eye – invulnerability. Since I cannot be killed, I don’t have to restart from a checkpoint. Our lua script can now become:

-- infinte lives
memory.writebyte(0x0011, 0x05)
-- invulnerability
memory.writebyte(0x0574, 0x7E)

My joy was very short lived. About half way through level 1, I met one enemy that won’t attack me:

wont-go down

The flying monster won’t come down and is to high up to be hit, so I cannot progress further. I guess somewhere in the game logic this enemy does not attack you until it can see you. And since I am invulnerable, it cannot see me. What I need at this point is a way to enable/disable the invisibility/invulnerability. Pressing the “select” button would do, as I don’t use it for anything. Ended up with this hackish script:

--infinte lifes. Can be called once at the start
memory.writebyte(0x0011, 0x05)

invisibility_enabled = false
while true do
  jp = joypad.read(1)
  if(jp.select) then
    invisibility_enabled = not invisibility_enabled
  end

  if invisibility_enabled then
    memory.writebyte(0x0574, 0x7F)
  else
    memory.writebyte(0x0574, 0x00) 
  end

  emu.message(tostring(invisibility_enabled))
  emu.frameadvance() 

end

Roughly, for each game cycle I am checking whether the select button was pressed. If so, I toggle the invisibility. I also display it on the screen (as true/false) so I keep track of the status.

This got me over level 1 easily. However, I realised that being invincible breaks the game easily. You can fall over the edges of the level or end up in places you cannot get out of. I guess that’s the reward for cheating. You can of course restart the game, but playing again through a number of levels does not sound fun. Luckly, it looks like there is a cheat to start from a specific level. You just add the level number at the 8320 memory location. However, this one needs to be timed to happen somewhere between pressing start on the main screen and starting level 1. While I guess there is a way to do it in the Lua script, I discovered a quick solution via Game Genie. Game Genie was an interesting device, better explained here . Roughly, this device would stay between your NES console and the ROM cartridge, sniff on all communication, look for specific memory address and change the values on the fly, allowing you to do short modifications, like infinite lives.

Fceux also “emulates” Game Genie, allowing you to generate codes. At Debugger > Game Genie Decoder/Encoder, you can transform an address/value/cmp into a genie code. Still from http://www.thealmightyguru.com/Games/Hacking/Wiki/index.php?title=Battletoads , I was able to generate a genie code that would allow me to start from any level. It is a bit manual, i.e. I have to regen the code if I want a different level, but it works fine. Overall, the game genie is a lot simpler to use than the Lua scripts, but also a lot more limited.

With all this in place, I was able to have infinite lives, toggle invisibility and start the game from any level. However, even with all this in place, the game was still very hard. While some levels, like the cave or the hole were extremely easy, there were others, like the snake pit, where you had the same hardcore NES experience. Using the invisibility was impossible since every wrong turn would send you in an unplayable state. Not using it would result in restarting the game tens or hundreds of times from the same checkpoint. In the end, I decided to watch a YouTube speed run and concentrate on easier games.

Thoughts on the Magento 2 Certified Professional exam

On March 1st 2018, the new Magento 2 Certified Professional Developer exam became available. Wanting to keep the tradition of getting my certifications early, I have attempted and passed the exam.

The exam experience is nice and easy as usual. You buy a voucher from https://u.magento.com/magento-2-certified-professional-developer#.WrtdjdNuZsY , then you can schedule an exam at a certified center. The exam has 60 multiple choice questions, a 90 minutes time limit and you get your results on the spot. It’s also possible to take the exam online, did not try it myself but Andreas did a nice write-up on this.

The exam is aimed at developers with about 1.5 years of experience with Magento 2. My opinion is that in order to pass you need to:

  • Have at least one full year of experience writing Magento 2 code.
  • Had the occasion to customize most of the Magento 2 areas, with a focus on backend
  • Are aware of the Magento best practices and apply them through your projects

Compared to the Magento 1 exam, this time a lot more value is put on proposing the correct architecture for a change. A fair number of questions is about doing things “the right way”. Sometimes solutions that work but are not correct are presented and you are expected to choose the ones that respect the best practices.

You can get away with very little CSS and JS knowledge (I guess a fronted developer certification will be coming out soon), but you are expected to know how to setup a theme, how to override templates or how to configure the ui components.

Besides the official guides, I encourage you reading the study guide and attempting the test exam from Swift Otter. The test exam is realistic, although I think it is a bit easier than the real thing. Personally I would have not passed without their guide. Other than that, having one year of hands-on Magento 2 experience is the only way to pass, no courses/magic formula to make up for it.

Overall, I consider this the best Magento 2 exam to date. More than ever, answering the questions correctly proves that you have experience with the platform and can deliver elegant solutions.