After working full-time with React.js for the past 2 years, I've now been 3 times lead React.js developer at 3 Series A startups. It's been a lot of fun, and after having gotten an early start in 2014, it's great to see it blowing up, growing 300% just in 2015 & 2016.

Below are a few of the higher-level things I've learned along the way, hopefully it'll provide you Denkanstoß (food for thought).

Roll your own

Let's say you want to implement an infinite list in React.js. (let's also assume that infinite lists are a solid UX choice)

When I faced this quiz, ultimately the right answer turned out to be the last one.

After implementing the first 3 I said "screw it" and decided to roll my own. With 3rd party libraries I kept running into problems such as strange markup choices & style structures that made it hard to style the component in line with existing set of components and with seatgeek's implementation in particular -- persistent performance problems (which I later tracked down to part of their code binding to the onScroll event, firing dozens of times per second)

The interesting distinction here seems to be that while jQuery defines things as changesets, which generally "work well enough", with React.js you have to define the exact state at any point in time. You are tightly bound by React's render cycle and can't simply "bind a few events handlers to make it do that thing when that other thing happens".

Since the app you're working on will generally develop it's very own look & feel, it can be hard to integrate 3rd party components that generally have been extracted from another codebase with its own idea of how to do HTML5, CSS, JS, React.js, browser compatibility, UX & accessibility in the year 2016.

Especially as you customize the behavior down the line, for complex and oft-used interactions, it makes a lot of sense to bite the bullet and roll your own.

It's been my ambition for some time to push forward a unified UI framework under which React developers can rally to concentrate their efforts. I'm happy to see CloudFlare push forward in this space with cf-ui, and hope that more people will push competitors as well as extensions to it.

Break the rules

React.js docs teach us to avoid forceUpdate

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component “pure” and your application much simpler and more efficient.

Use data-fetching containers

The gist is, have your representational components (the ones with the markup) be completely unaware of how they get their data, and if their data is even there. This should be handled by a parent component whose job it is to get the data, massage it if necessary, trim it to shape, and finally render the representational component.

React is not a religion

React & Redux generally front-loads a lot of pain.

Wanna have a thing that changes on the page. OK, please define exactly how I should render the entire page under all circumstances.

Want to have a new button? OK, please define a new action identifier, a new action, put the button state into the reducer, as well as the initial state, and now pass the new state through the entire application to where you want it.

Want to have a drag-and-drop interaction? OK, please set aside a day to familiarize yourself with react-dnd and its DragSource, DragLayer, DropTarget & DragDropContext components. Then you can define a collect function that connects the drag source and sets isDragging on the monitor as well as a new ItemType for whatever you want to drag as well as an itemSource which is a plain object with a beginDrag function on it. Now you can use those to instantiate a new DragSource and directly call the class of React component you want to drag around with that.

You can't deny, there's something seductive about jQuery:

<divclass="dragon">DRAG ON ME</div>

$('.dragon').draggable({ grid: [ 20, 20 ] })

Boom, done!

But if you try getting a React.js component to be draggable along a grid, you'll wind up writing a crazy 800 line react-dnd monstrosity, that is specific to this one drag UX interaction, and that none of your coworkers will ever want to touch.

Not that would have ever done that.

React's core philosophy evolved out of the work Facebook's engineers did on XHP. A PHP extension to help them manage the massive complexity they were dealing with.

As such it only really starts to shine once your project eclipses a certain size & complexity.

What good is beautiful code, thrown away?

Use the best tools

Immutable.js

While there is the initial hurdle, immutable.js will make your code easier to reason about, safer to manipulate, and will save hours debugging. Immutable data structures truly are a godsend.

Webpack

Use webpack, rather than Browserify or requite to pull together your project, react-hot-loader and a plethora of other amazing tools are built on top of it -- it is the way forward.

redux-thunk allows you to return thunks rather than action inside actions creators. Inside the thunk (which is basically just a function) you can delay the action, or dispatch depending on certain conditions.

Hot reloading will make your React development a lot faster: react-transform-boilerplate. It detects which components have changed, and only re-renders those. Rather than waiting 5s for webpack to rebuild your entire project, and waiting for your entire browser to rebuild the site, you get sub-second feedback.

Webpack Dev Server

If you don't fancy Hot Reloading, at least do yourself the favor of using webpack-dev-server. It's been one of those "I wish I had done this sooner" moments for me.

That's it! If you have questions or suggestions for improvement, please do not hesitate to contact me at dominik@doda.co

At this point I'd been working with Django and Django REST Framework for years, so thought to myself: Upgrading a 3rd party library from 2to3, easy pickings! Change a few field names and maybe some Serializer method names. I like Serializers. Serializers are cool.

A first

$ pip install -U djangorestframework
$ python manage.py runserver

revealed a large amount of assertion errors coming from the DRF 3 source code.

Code like this:

class Field(object):
def __init__(...):
# Some combinations of keyword arguments do not make sense.
assert not (read_only and write_only), NOT_READ_ONLY_WRITE_ONLY
assert not (read_only and required), NOT_READ_ONLY_REQUIRED
assert not (required and default is not empty), NOT_REQUIRED_DEFAULT
assert not (read_only and self.__class__ == Field), USE_READONLYFIELD

Every code base is unique, but I've compiled a list of ideas that helped me through the process:

Read the announcement. You'd think this would be obvious and the announcement actually tells you to read it too, but one thing that would've helped me tremendeously was if it had done so in bold red. Read the page! -- Yes. That is better.

Familiarise yourself with the DRF3 source before starting. What exactly do BaseSerializers, Serializers, ModelSerializers do and when do you want to sub-class each one? What's the difference between .data and .validated_data (hint: it's not the validation). How does validation work now anyway? Why does DRF3 not call Model.clean() anymore when de-serializing? Should you instantiate a throw-away in order to runModel(**data).clean() or maybe move the validation code into a more generalised spot? The announcement and DRF3 source code (which is well documented) will help with such questions.

Set all the compatibility flags in the beginning and work backwards. DRF3 coerces beautiful native Date, Time, DateTime and Decimal objects into strings in Serializer output ... setting DATETIME_FORMAT, DATE_FORMAT, TIME_FORMAT to None and COERCE_DECIMAL_TO_STRING to False respectively will revert such behaviour.

Get to green as quickly as possible. I started working through the test failures on a submodule-by-submodule basis but midway through went rambo and started to leave small optimisations, refactors & cleanups by the way-side and went into hack-mode spraying code and TODO's wherever I went in an effort to "just get to green" on my test build and have a solid basis to work from. After this was done, I also had a better overview of the which problems kept reoccuring and required careful refactoring and which ones were one-offs that could be left as special cases.

Leave bugs that confuse you for later. When all of a sudden completely unrelated code starts breaking, it might be a good idea to leave it and focus on the more concrete stuff first. This ties in with Get to green as quickly as possible. Some things are obviously wrong behaviour, while others can simply be a special case that was intended but undocumented, or a new DRF3 behaviour, or an old DRF2 behaviour that's not possible anymore, or a different output format causing something else to behave differently in subtle ways, and so on and so forth.

Here's the example of a create flow for one of the Serializers

You would probably be right to assume that this can and will break in many places if you completely re-architecture the APIs and under-lying philosophies of the code the white and gold blue and purple rows were built upon.

Imagine the CustomAddressField throws a ValidationError. After tracing through the code you find while the value originates in gen_contact_details(), it sometimes gets modified in fill_project_data(), a utility function used widely throughout the 300kLOC code base. What is this mysterious value supposed to be? Searching through the code base some other function tries to cast this value into an int() after calling fill_project_data() but leaves it be incase it can't do it. This means it must be str orint in most cases, maybe a float. Since we're using dynamically typed Python, there's a lot of guess-work involved. Leaving hard-to-debug errors for later gives you more time to get to know your own code base and those of DRF2 and DRF3.

A lot of the time opaque high-level failures will resolve themselves when you get to the more fine-grained tests and are able to quickly pin-point & solve issues at a lower level.

Ration your willpower. Carefully stepping through nested upon nested levels of testing + view + serializer + DRF3 source code is mentally taxing work and I decided to reserve my most productive phases of the day for the heavier mental lifting while picking out easier tasks otherwise. There's no shame in switching to a more pedestrian JavaScript bug late in the day, when the same time tomorrow could also be spent working on something tougher.

Don't be afraid to go against what you see in the DRF3 source. A lot of the implicit behaviors in DRF 2 have been replaced by stricter and more explicit ones in DRF3. I enjoy code-philosophical discourse as much as the next guy, but sometimes re-implementing a bit of woo-woo and magic can be an easier way to keep API consistency than to try and shove a DRF2-grown cactus into a DRF3-shaped pot.

Was it worth it?

For me personally: Yes. While altogether a rather bumpy & long ride, I believe it's often the things we don't enjoy at first that help us grow. Serializers were one of the areas I was less familiar with and I now - quite literally - know every nook and cranny of the small little beasts.

Like other big projects the reasons for upgrading from version 2 to 3 are not quite obvious. Under the hood it's a lot nicer. And there's quite a few goodies. At the same time all this goes against the maxim of "If it ain't broke, don't fix it".

I wonder if there's something about working on large open-source code-bases, where a v3makes developers & maintainers snap and spiral into a we-do-things-like-this-now frenzy because working with the old code day-in-day-out simply becomes too intellectually & aesthetically insulting.

Over-communicate

Remote work compresses your emotions, your subtle hinting, your non-verbal social cues down by a lot.

The question "should I add this to clarify" should almost always be answered with a "yes". There is tremendous value in being terse, but since humans tend to read a lot faster than they write, you can help your team and your clients a lot by providing additional signal. Write, write, write.

Listen

Rather than blindly ascribing malintent, it's often more effective to ask specific "why?" questions to get behind people's beliefs and motivations. Listen to what they are saying. And even if what they are saying makes no sense and you feel that urge to interrupt and correct them, don't.

People want to be heard, it makes them feel good. Be that person for others.

Hold your tongue

There will be moments when you feel slighted. Treated unfairly or misunderstood. You'll feel shame and anger.

Especially in the realm of ASCII-communications, sitting in your room with little emotional outlet, this can quickly lead to

dra·maˈdrämə/

an exciting, emotional, or unexpected series of events or set of circumstances

Here are a few of the tricks I use whenever I feel negative emotions coming up:

Walk away. Simply going for walk gives you a nice temporal and physical buffer from saying things you might regret.

Put yourself in their shoes. This as one of the most powerful, there's almost always good reasons why people do the things they do.

Type it and delete it. Type out an email detailing all the ways you think you're being treated unfairly and how everything and everyone sucks, and then delete it.

Make light of the situation. This is one of the heavier ones, but it is tremendously powerful: I assume a nasal voice and say to myself: "Aww, poor little Dominik, he gets to work for an awesome startup with the tech he loves to use and from wherever he wants. And now he has to put up with a little bit of negative emotions.... Aww, what a poor little Dominik". This almost always causes me to crack up.

See the bigger picture. Whenever I navigate a tricky situation like this, I pat myself on the back. Change comes slowly but every positive interaction puts me further on track to becoming the person I want to be.

Turn up the volume

Hey, this article is about rocking remote right?

No more having to be sensitive towards the people in your office!

So turn up the speakers, blast some music, do a little dance after your tests pass and scream out the window Flogsta-style for the sheer joy of it:

Trick yourself

Working in an office can make starting tasks easier: There is a cost associated with being seen bumming around on reddit.

In order to create the same social pressure for myself I've used livecoding.tv in the past. Even 3 people watching you code makes it all that more important.

Another trick is to pick a tiny part, i.e. just throwing up the markup with no functionality. Once you're in flow, doing the actual work will seem like the most natural thing.

Have one on the back-burner

Since asynchronous communication sometimes means having to wait, I always try to have a small, independent task stored away. This might be filling out a test suite, improving documentation, or investigating an edge-case bug.

A great way to handle this is to never run into it. When taking on a new task, explore in your mind the tree of eventualities and bring them up before starting. Asking even the improbable will give you a better understanding of what your client / boss, has in mind.

Be like water

Look around you, your monitor, your laptop, your desk, your shoes. All are products of collaboration between thousands of people.

Producing the cleanest, highest-quality code is a great goal. I strive for it every day.

But coming into a new project I try to leave my preconceived notions about how things "should be done" at the door. Especially in terms of coding style, there a lot of arguments every which way. What matters more is to assimilate to the current way of things, in order to reduce friction and so you can all pull into one direction.

Your work area matters

I use a standing desk with a standing mat to reduce strain, a Kinesis Advantage, a 2560x1440 monitor lifted to just below eye level, and all this next to a large window so I get as much sunlight as possible. I clear stuff off my desk as quickly as I can.

Working out of coffee shops, or while traveling is certainly possible. But every little decision, every distraction takes away from willpower that I could dedicate to the project I'm working on.

Keep a schedule

I probably have the best ideas in the shower, yet, despite the drive to work on a project 24/7 I've found the best results when I work a normal day's schedule. Get up early, make coffee, put on nice clothes, make the bed. Go for a walk to get those 20 minutes of direct sunlight exposure. End the day at a reasonable time.

Hacking away at 2am is fun, but every minute spent in that twilight zone removes you a bit further from normal people working a 9-5 and makes socializing harder than it already is. Grabbing a beer with friends at 6pm when you've starting working at 12? Preposterous.

Schedule one-on-ones

Goals, priorities, targets can change quickly, especially in startups. Make sure to schedule regular 1-on-1s with your boss (really push for them). You are helping them by relieving them of the burden of herding all their developers.

But isn’t one of the signs of a well-working team that they require little communication?

If you're absolutely sure that there's nothing to talk about, go ahead. But if you aren't, talk anyway, you would be surprised the little things that come up, and the nuances in communication you can convey via tone of voice.

No faking

Whereas in an office environment you can come to work hung-over and spend 8 hours chair-bound and you're unlikely to be caught out for it.

That quickly stops working with remote work. You are your results, especially as a freelancer. If you feel you aren't doing your best work, it's a good idea to bill fewer hours (e.g. bill 6 for 8 worked). Under-promise, over-deliver.

Have fun

Share as much as you can with your co-workers. Funny stories, stupid mistakes, lessons learnt, interesting articles. This attitude of personal vulnerability (not everyone's perfect) and extroversion (positive, but maybe shallow connection) creates an open & trusting space that others want to be in.

My story with Ivo starts in Berlin in July. Sweaty, sticky, dusty Berlin in the summer.

Backpacker hostel. Hung over on a Wednesday, unemployed, just moved from London to look for a job. Exploring Berlin every day with new friends made in hostels. Sitting in the 8-man room in Kreuzberg barely managing to connect the spotty WiFi. Ivo, recruiter for a lot of the best startups in Berlin, calls through.

And starts asking a lot of questions about my past experience. "Whatever man, just send them my CV", I'm thinking. He's not technical ... so what I'm saying will probably either not be understood and/or misremembered anyway.

But despite a bumpy start to the conversation and me giving every indication that I'd rather not be talking to him, Ivo persists. And with his disarming demeanour, he manages to get a 30-minute conversation out of me.

In the process Ivo connects me to the job I didn't even have the courage to apply to. I get the offer and am exstatic. Thank you Ivo.

Fast-forward 6 months. The startup has imploded and I'm feeling it's finally time to make my push into the freelancing world. After handing in my resignation, I shoot Ivo a quick email whether he knew something. 3 months prior Ivo took the time to follow up with how I liked the job -- I felt like he cared so I wanted to let him know what happened.

We schedule a call but when Thursday 4pm rolls around I'm just waking up from a nap (hello funemployment) and really don't feel like talking to anyone.

I rationalise the resistance ... "Recruiters don't have the good opportunities anyway". "It's probably gonna be a waste of time".[0] And so Skype rings.

And rings. 410pm. 420pm. 434pm. But Ivo persists. Skype is still ringing. Boop-boop boop-boop.. At this point 2 things have kicked in: My internal "detect-my-own-BS-o-meter" making me more aware that talking to him is actually probably what I want to be doing. And a feeling of pity ... he really wants to talk to me... Fine, OK.

But I hear you saying "Ivo is just a recruiter ... isn't this his job?"

Yes.

But having talked to so many recruiters over the years, they failed where Ivo succeeded. What makes him different?

Ivo is genuinely interested in you. Ivo listens patiently and he never interrupts. His calm demeanour disarms you. Rude remarks don't even ping on his radar, Ivo forgives.

It is for this reason that in my personal relationships I strive to be more Ivo. To not take my asocial moods so seriously. To be interested in others.[1] To not say too much. To not take things personally. To be more extroverted. To be more forgiving. To persist.

To be more Ivo.

[0] (unlike lying in bed)

[1] Everyone is plagued by insecurities and self-doubts. If we want to give them the power to connect to uswe must make them feel like we care to hear what they are saying. Maybe sometimes not for the content, but because time spent talking bonds andbuilds familiarity & trust.

The greatest cultural extravaganza that one could imagine. –David Bowie

Queers, creatives & outcasts living inside a sprawling landscape of history, Berlin bakes a crazy cake. Stepping from my door into this city holds a surprise always. From a homeless person offering me a beer in return for a smile, a woman calling out another for standing in my way (she was), a stranger berating me for my bad breath (it was) or a super market employee complaining about me dragging my feet (I was), to the endless crazies on the U-Bahn, I appreciate it all for it means there is something rather than nothing. Berlin still believes we can all improve and it's not shy to say so. If maybe you find not happiness but self-expression and congruence (being real yo) worthwhile pursuits, then Berlin will keep on giving.

You're unlikely to become friends with Berliners. What I've found, Germans tend to prefer deep relationships over shallow ones. When first moving here I'd been a few times straight-up rejected someone's Facebook or phone number, unthinkable in the US or UK where people are happy to give out contact details, if only to end an interaction. Germans often stay in the social circle they've built up through work, high school or university, unwilling to put in the effort of strangers.

Berliners tend to have 3 kieze (kiez being the Berlin term for a neighbourhood or borough), one kiez they live in, one kiez they work in and one kiez they go out in. With the city being so sprawled out and more like a collection of smaller citites, finding things becomes harder. Searching for a Yoga studio, I tried a couple and was left wanting, even at the biggest andmost famous one ... until the last day when a great teacher held an intense class ... all throughout me grinning at her for finally giving me what I'd been missing. Only to find out she actually teaches in NYC... London and NYC tend to have fewer, centralised options that have withstood high competitive pressure for years offering servicese that are more refined, standardised. Berlin likes to pride itself on an individuality, collaboration, other players even, are of little interest.

Berlin is very gay, both for emotion as well as mechanism of attraction. I've been described as a touchy-feely person in the past, but Belin's taught me to tread more carefully. One thing I've learned very quickly when approaching another man or being approached is to drop some comment about girls ("Deutsche Frauen oh ja!"). This usually builds rapport as well as establishing the outset of the relationship. These tactical considerations aside, my gay friends here are amazing, expressive, joyful and understanding people and I wouldn't miss them for anything.

Berlin dresses down. And that is quite sad, unlike London and NYC where people actively push & try new things, Berlin's style feels quite out-dated and bland. London's street style is a joyous ode to colours, textures and shapes. Berlin's street style is a mish-mash of grey, black, brown clothes in odd, outdated shapes. With dirt everywhere, I've also started to veer towards grey and black-tones. Trying new things with clothes in London adds to the mix, in Berlin it makes you one of the weirdos.

Berlin is a city condemned forever to becoming and never to being." -Karl Scheffler

Rents are low, space is vast, opportunity is ripe. And this attracts many youngs and hopefuls. They come empty, they come wanting, needing. Wanting experiences that stretch. Wanting to be understood, for the first time in their life. And for this they are willing to give. Their energy, their time, their Euros. And they go through that cold winter to find each other in places that stimulate them, be it at Berghain where the speakers make them feel music so deep, jaws gnawing. Or at a philosophy meetup in P'Berg debating happiness, work, motivation and life purpose into the early morning hours. Berlin hosts people from all walks of life, some rising to incredible heights, others falling into the endless cycle of drugs & parties.

8 months in I can't say the cold & dark Berlin winter hasn't made me look lustfully towards say Brazil or Thailand, but for the sheer opportunity, quality of life and personal as well as cultural freedom, I'm happy to call Berlin my new home on the Spree.

In my years of programming in Python and roaming around GitHub's Explore section, I've come across a few libraries that stood out to me as being particularly enjoyable to use. This blog post is an attempt to further spread that knowledge.

I decided to exclude awesome libraries like requests, SQLAlchemy, Flask, fabricetc. because I think they're already pretty "main-stream". If you know what you're trying to do, it's almost guaranteed that you'll stumble over the aforementioned. This is a list of libraries that in my opinion should be better known, but aren't.

pip install pyquery

For parsing HTML in Python, Beautiful Soup is oft recommended and it does a great job. It sports a good pythonic API and it's easy to find introductory guides on the web. All is good in parsing-land .. until you want to parse more than a dozen documents at a time and immediately run head-first into performance problems. It's - simply put - very, very slow.

What immediately stands out is how fast lxml is. Compared to Beautiful Soup, the lxml docs are pretty sparse and that's what originally kept me from adopting this mustang of a parsing library. lxml is pretty clunky to use. Yeah you can learn and use Xpath or cssselect to select specific elements out of the tree and it becomes kind of tolerable. But once you've selected the elements that you actually want to get, you have to navigate the labyrinth of attributes lxml exposes, some containing the bits you want to get at, but the vast majority just returning None. This becomes easier after a couple dozen uses but it remains unintuitive.

pip install watchdog

watchdog is a Python API and shell utilities to monitor file system events. This means you can watch some directory and define a "push-based" system. Watchdog supports all kinds of problems. A solid piece of engineering that does it much better than the 5 or so libraries I tried before finding out about it.

That listdir is in os and not os.path is unfortunate and unexpected and one would really hope for more from such a prominent module. And then all this manual fiddling for what really should be as simple as possible.

Best part of it all? path subclasses Python's str so you can use it completely guilt-free without constantly being forced to cast it to str and worrying about libraries that checkisinstance(s, basestring) (or even worse isinstance(s, str)).

That's it! I hope I was able to introduce you to some libraries you didn't know before.