Just-Eat spectrum-bottom spectrum-top facebook google-plus instagram linkedIn pinterest reddit rss twitter_like twitter_reply twitter_share twitter_veriviedtwitter vimeo whatsapp youtube error_filled error file info-filled info loading star tick arrow arrowLeft arrowRight close download minus-filled minus move play plus-filled plus searchIcon settings

136 views

OWASP meetup in Just Eat

We are looking forward to tonight’s OWASP London Chapter event at Just Eat offices in London. We will start broadcasting live at 6:30 PM UK time today. 

watch live now on youtube

OWASP

612 views

Troy Hunt – Hack Yourself First workshop at Just Eat

2016 was a year full of internet security issues from the Yahoo breach, to TalkTalk hack to US Election rigging and the massive Tesco Bank breach to an Internet crippling DDoS attack. Today, internet security is now no longer just the domain of techies and security experts, but the responsibility of all of us.

Hacked website

A close-up of Troy Hunt’s demo site with hacked videos inserted

I remember my first computer. It was a ZX Spectrum, running with 48K of RAM on a Z80 processor running at 3.5 MHz. It was on this rubber-keyed machine that I learnt about for loops, if clauses and how much fun it was getting a computer to do your bidding, even if it was only to print “HELLO” all the way down the screen.

Hello Hello

Today, many years later, I spend most days getting Just Eat’s computers to do what I want them to do. And it’s still as satisfying as it always was.

A few weeks ago, Troy Hunt came and visited Just Eat for the second year running, to lead a fresh group of our engineers through his two-day ‘Hack Yourself First’ security workshop. And I learned something new and interesting – how to get other people’s computers to do what I wanted them to…

(For those of you who don’t know, Troy is one of the world’s best known web security experts.)

Troy Hunt sees hacked site for the first time

Troy Hunt discovers his test site has been hacked by Rick Astley

Twenty Just Eat engineers participated in the workshop, which consisted of a mixture of an overview of some of the most common security flaws out there in the wild, taking us gently (and sometimes not-so-gently) through (among other things) SQL injection attacks, badly configured applications and poorly thought-out password policies. Not only did he show us what the implications were when these things happened, but showed us how to get our hands dirty and hack a demonstration website that he had made specifically to be hacked.

Now my interest was piqued. Of course, as a seasoned developer, I’d heard about most of the security flaws that Troy was talking about, but actually being able to hack a site and see what information gets compromised: getting someone else’s computer to do what I wanted it to do was even more satisfying than getting my own one to behave: having my trusty laptop break a website (albeit one written purposely to have these security holes), spam its reviews, and enumerate through all the registered users’ details in less than ten minutes was an eye-opener.

Rick-rolled Troy Hunt

Troy Hunt discovers his test site has been hacked

Troy’s workshop helped all of us to understand, through our own practical application & experience, that security is something we must all take responsibility for, and how to do this in a practical way.

Troy continues to be instrumental in highlighting security issues, and showing how to prevent or combat them (through his blog, his database of data leaks and his online courses). Our thanks to Troy for spending a couple of days giving us a fairly broad yet deep dive into some of these issues.

I for one was inspired to look deeper into this fascinating part of our industry, and the feedback suggests it wasn’t just me!

 

698 views

Xamarin 101, S01E01 – UI Tests

Xamarin 101 is a new series that we hope will prepare you and your team to use Xamarin in production. Each episode will focus on one particular topic on Xamarin development.

Subscribe to our meetup page to receive notifications about all our future events including the next Xamarin 101 episodes, we’ll also give you free pizza and drinks whilst you learn, win-win.
//www.meetup.com/London-Mobile-Dev.

Our first episode was about UI Tests, the full presentation is now available on our Youtube channel!

Two of our JUST EAT Xamarin Engineers also spoke at the event.

Xamarin UITest and Xamarin Test Cloud by Gavin Bryan

This talk covered Xamarin’s Automation Test library, which allows you to create, deploy and run automation tests on mobile devices, simulators and emulators. The library is based on Calabash and allows you to write automation tests in C# using NUnit in a cross-platform manner so that tests can be shared across different platforms if required.
The library is very rich in functionality, allowing quite involved and complex automation tests to be written. The talk gave an overview of some basic test automation and tools available for creating and running tests. The automation tests can be run both locally, in CI environments and in Xamarin Test Cloud (XTC). XTC is an on-demand cloud based service with over 2000 real mobile devices available to run your automation tests on.
We showed the options available for running automation tests on a variety of devices in XTC and showed the analysis and reporting that was available in XTC.

 

Presentation Assets
Slides – goo.gl/TXTVzI
Demo – goo.gl/QiKprk

____

BDD in Xamarin with Specflow and Xamarin UITest by Emanuel Amiguinho

Following Gavin’s presentation, it was time to bring BDD to Xamarin development using Specflow to fill in the gap between Gherkin Feature/Steps definition and Xamarin.UITest framework to have the best UI test coverage possible and good documentation that everyone inside of your team can understand (technical and non-technical personnel).

Presentation Assets
Slides – goo.gl/ITWen8
Demo – goo.gl/7BDpfp

____

Our next topic is databases and we are currently looking for speakers that have had experience with any type of local database in their development (SQLite, DocumentDB, Realm database, etc). If you are interested, please send an email outlining which database you want to talk about and your availability to:
emanuel.amiguinho@just-eat.com or nathan.lecoanet@just-eat.com

589 views

How to abstract your persistence layer and migrate to another one on iOS with JustPersist

just_persist_banner

In this blog post we introduce a solution to deal with data persistence. We developed it for the Just Eat iOS app and we call it JustPersist. It’s available open source on Github at github.com/justeat/JustPersist.

JustPersist aims to be the easiest and safest way to do persistence on iOS with Core Data support out of the box. It also allows you to migrate to any new persistence framework with minimal effort.

The main author behind JustPersist and its design is Keith Moon. Major kudos to Keith for the excellent execution in Swift!

Overview

At Just Eat, we persist a variety of data in the iOS app. In 2014 we decided to use MagicalRecord as a wrapper on top of Core Data but over time the numerous problems and fundamental thread-safety issues, arose. In 2017, MagicalRecord is not supported anymore and new solutions look more appealing. We decided to adopt Skopelos: a much younger and lightweight Core Data stack, with a simpler design, developed by Alberto De Bortoli, one of our engineers. The design of the persistence layer interface gets inspiration from Skopelos as well, and we invite the reader to take a look at its documentation.

The main problem in adopting a new persistence solution is migrating to it. It is rarely easy, especially if the legacy codebase doesn’t hide the adopted framework (in our case MagicalRecord) but rather spread it around in view controllers, managers, helper classes, categories and sometimes views. Ultimately, in the case of Core Data, there is a single persistent store and this is enough to make impossible to move access across “one at a time”. There can only be one active persistence solution at a time.

We believe this is a very common problem, especially in the mobile world. We created JustPersist for this precise reason and to ease the migration process.

At the end of the day, JustPersist is two things:

  • a persistence layer with a clear and simple interface for transactional readings and writings (Skopelos-style)
  • a solution to migrate from one persistence layer to another with (we believe) the minimum possible effort

JustPersist aims to be the easiest and safest way to do persistence on iOS. It supports Core Data out of the box and can be extended to transparently support other frameworks. Since moving from MagicalRecord to Skopelos, we provide available wrappers for these two frameworks.

The tone of JustPersist is very much Core Data-oriented but it enables you to migrate to any other persistence framework if a custom data store (wrapper) is implemented (in-memory, key-value store, even Realm if you are brave enough).

JustPersist is available through CocoaPods. To install it, simply add the following line to your Podfile:

Using only pod JustPersist will add the core pod with no subspecs and you’ll have to implement your own wrapper to use the it. If you intend to extend JustPersist to support other frameworks, we suggest creating a subspec.

Usage of the persistence layer

To perform operation you need a data store, which you can setup like this (or see “common way of setting up a data store”):

Before using the data store for the first time, you must call setup() on it, and possibly tearDown() when you are completely done with it.

We suggest setting up the stack at app startup time, in the applicationDidFinishLaunchingWithOptions method in the AppDelegate and to tear it down at the end of the life cycle of your entire app, when resetting the state of the app (if you provide support to do so) or in the tearDown method of your unit tests suite.

To hide the underlying persistence framework used, JustPersist provides things that conform to DataStoreItem and MutableDataStoreItem, rather than the CoreData specific NSManagedObject. These protocols provide access to properties using objectForKey and setObject:forKey: methods.

In the case of Core Data, JustPersist provides an extension to NSManagedObject to make it conforming to MutableDataStoreItem.

Readings and writings

The separation between readings and writings is the foundation of JustPersist.
Reading are always synchronous by design:

While writings can be both synchronous or asynchronous:

The accessor provided by the blocks can be a read one (DataStoreReadAccessor) or a read/write one (DataStoreReadWriteAccessor). Read accessors allow you to do read operations such as:

While the read/write ones allow you to perform a complete set of CRUD operations:

To perform an operation you might need a DataStoreRequest which can be customized with itemType, an NSPredicate, an array of NSSortDescriptor, offset and limit. Think of it as the corresponding Core Data’s NSFetchRequest.

Here are some complete examples:

In write blocks there is no need to make any call to a save method. Since it would be the obvious thing to do at the end of a transactional block, JustPersist does it for you. Read blocks are not meant to modify the store and you wouldn’t even have the API available to do so (unless DataStoreItem objects are casted to NSManagedObject in the case of CoreData to allow the setting of properties), therefore a save will not be performed under the hood.

Common way of setting up a data store

We recommend to use dependency injection to pass the data store around but sometimes it might be hard. If you wish to access your data store via a singleton, here is how your app could create a shared instance for the DataStoreClient (e.g. DataStoreClient.swift) using Skopelos.

For unit tests, you might want to use the inMemoryShared for better performance.

Child data store

A child data store is useful in situations where you might have the need to rollback all the changes performed in a specific section of the app or in a part of the user journey. Think of it as a scratch/disposable context in the Core Data stack by Marcus Zarra.

At Just Eat we use a child data store for the addition of complex products to the basket. The user might make many updates to the product and it is easier to perform the final save operation when the user confirms the addition rather than dealing with multiple CRUD operations on the main data store.

A child data store behaves just like a normal data store, with the only exception that, to save the changes back to the main data store, developers must explicitly merge the data stores. Here is a complete example:

Thread-safety notes

Read and sync write blocks are always performed on the main thread, no matter which thread calls them.
Async write blocks are always performed on a background thread.

Sync writings return only when the changes are persisted (in the case of Core Data, usually to the NSManagedObjectContext with main concurrency type).

Async writings return immediately and leave the job of saving to the source of truth to JustPersist (whether it be the context or a persistent store). They are eventual consistent, meaning that the next reading could potentially not have the data available.

Forcing a transactional programming model for readings and writings helps developers to avoid thread-safety issues which in Core Data can be caught setting the -com.apple.CoreData.ConcurrencyDebug 1 flag in your scheme (which we recommend enabling).

How to migrate to a different persistence layer

Examples in this sections are in Objective-C as 1. they deal with the legacy code for the nature of the example and 2. to show that JustPersist works just fine with Objective-C too.

Here we’ll outline the steps we made to migrate away from MagicalRecord to Skopelos using JustPersist. We believe that a lot of apps still use MagicalRecord, so this may apply to your case too. If your need is to move from and to other 2 frameworks, you need to implement the corresponding data stores to wrap them.

You should start by implementing your DataStoreClient (you could follow the steps in “common way of setting up a data store” and allocating the data store for the current persistence layer used by your app in the sqliteStack method and possibly in the inMemoryStack one too. In our case, since we want to move away from MagicalRecord, the data store used would be MagicalRecordDataStore.

Standard CRUD interactions with MagicalRecord are like so:

All of them should be converted one by one to JustPersist:

You should make sure you don’t perform any UI work within the blocks even if the read and writeSync ones are executed on the main thread. Actually, you should aim for doing only the necessary work related to interact with the persistence layer, which often might be copying values out of objects to have them accessible outside the block (in Objective-C via the __block keyword). Developers should not hold references to model objects to pass them around threads (transactional blocks help ensure such rule).

By having moved all the direct interactions from MagicalRecord to JustPersist, you should be now able to remove all the various @import MagicalRecord and #import <MagicalRecord/MagicalRecord.h> from the entire codebase.

Once At this point, your DataStoreClient can be modified to allocate the target data store in the sqliteStack and inMemoryStack methods. In our case, the SkopelosDataStore.

Conclusion

JustPersist aims to be the easiest and safest way to do persistence on iOS. It supports Core Data out of the box and can be extended to transparently support other frameworks.

You can use JustPersist to migrate from one persistence layer to another with minimal effort. Since we moved from MagicalRecord to Skopelos, we provide available wrappers for these two frameworks.

At its core, JustPersist is a persistence layer with a clear and simple interface to do transactional readings and writings, taking inspirations from Skopelos where readings and writings are separated by design.

We hope this library will ease the process of setting up a persistence stack, avoiding the common headache of Core Data and potential threading pitfalls.

About the authors

Alberto De Bortoli is the Principal iOS Engineer at Just Eat.
Keith Moon is a Senior iOS Engineer in the Payments team at Just Eat.

912 views

iOS Event tracking with JustTrack

Overview

At Just Eat, tracking events is a fundamental part of our business analysis and the information we collect informs our technical and strategic decisions. To collect the information required we needed a flexible, future-proof and easy to use tracking system that enables us to add, remove and swap the underlying integrations with analytical systems and services with minimal impact on our applications’ code. We also wanted to solve the problem of keeping the required event metadata up-to-date whenever the requirements change.

JustTrack is the event tracking solution we built for that and it’s available open source on Github at //github.com/justeat/JustTrack.

Examples and documentation are available in the Github repository Readme.

Main features

  • Events are declared in a .plist file and Swift 3 code is automatically generated at build time from it.
  • Events can be sent to multiple destinations (called Trackers) at the same time.
  • Custom Trackers are easy to create and use.

Events Definition

One of the problems we found with existing solutions is that the events are declared in code and therefore can only be maintained by developers. Similarly, existing solutions offer very generic tracking facilities for developers. Because of that, whenever the required metadata associated with an event changes for any reason, the developer has to search the code base and update all instances of the event with the correct implementation. This, of course, is a very fragile process and is prone to errors.

JustTrack solves these problems by declaring events in a plist file that is used to automatically generate equivalent definitions of the events in Swift that can be used in the app. This provides several benefits:

  • Each event is uniquely identified.
  • The metadata associated with each event is type checked.
  • When the requirements for an event change, the developers can see it through build errors and warnings that will naturally occur.
  • Plists can be edited as XML, which means anybody in the business can edit them.
  • It’s easy to search for events that are no longer used and deleted events won’t compile.

An Event is made of:

  • Name: the unique identifier
  • Registered Trackers: List of event destinations (e.g. Google Analytics)
  • Payload: The metadata associated with the event (at this time only String key-value pairs are supported)

Trackers

Another problem we found with existing solutions is that, generally speaking, all the events need to be tracked with the same Trackers. The developer doesn’t have any freedom to decide which event goes to which Tracker, and several solutions only support specific tracking technologies (such as GA, Firebase, and so on)

JustTrack solves this problem by allowing the developer to specify the “registered” trackers for each event and to create custom trackers.

A Tracker is an object implementing the JETracker protocol and is loaded using: tracker.loadCustomTracker( ... ) function. You can implement any tracker you want and JustTrack provides a few default trackers:

  • JETrackerConsole – print events to the system’s console
  • JEFacebookTraker (not yet implemented)
  • JEGoogleAnalyticsTraker (not yet implemented, Google’s pods can’t be used as a dependency in a pod)
  • JETrakerFirebase (not yet implemented, Google’s pods can’t be used as a dependency in a pod)

Conclusions

Using JustTrack you can easily track your app’s events to multiple destinations, having all the necessaire flexibility, intrinsic events documentation and all the expandability you will ever need in future, all of that writing the minimum amount of code possible.

About the author

Federico Cappelli is a Senior iOS Engineer and iOS COG Leader at Just Eat.