In this blog post, I share my recent experience in a UI project, as a developer with limited past experience in UI development. I published this internally on REA Group's wiki a while back to foster interest in UI projects from a broader set of developers - highlighting that solid engineering is a big part of contemporary UI development.
This is not specific to REA, hence I was keen to share this journey externally on our blog.
A little bit about my background
Before joining REA Group (realestate.com.au), I had worked as a back-end developer on a number of large monolithic Java applications at different companies. At REA, except for more recently, I've been mainly involved in building Scala micro-services. My experience with front-end development in the past has been limited. Like most other back-end developers though, I’ve worked on projects which have had a mixture of back-end and front-end components; so I’ve occasionally used front-end technologies such as JSPs (a very long time ago), YUI, JSF, jQuery and AngularJS.
But for the most part, I had considered myself a back-end developer. When asked for example by recruiters in the past if I’m interested in front-end or back-end roles, I had always expressed interest in doing back-end.
Joining the realestate.com.au UI re-platforming project
A while back, I was asked by Alison Rosewarne (who was tech lead at the time in our team) to join a UI project as a lead developer. The project was to re-platform the realestate.com.au listing experience UI to a universal ReactJS application. I was initially very hesitant to join that team for various reasons:
I didn’t think I would be able to contribute much
Given my lack of front-end skills, I didn’t think I'd be able to contribute much in a UI-heavy project. My experience with CSS in the past, had mostly been something like this:
It usually takes me hours to make something on a web page look good, only to realise at the end that I’ve broken something else on the page.
To be honest, I didn’t think I would enjoy it
This kinda relates to my previous point. If you don’t think you're good at something, most likely you won’t enjoy it; unless you challenge yourself to learn it. I already felt challenged enough though with things I was learning in back-end projects at that point of time (elasticsearch, functional programming, etc.), so wasn't highly motivated to pick up something else.
I had a lot to learn
I felt overwhelmed by the number of things I had to learn to become productive in UI land.
This list is changing all the time. New technologies replace the old ones much more quickly in front-end compared to back-end.
Despite all these, Alison suggested that there will be need for developers with experience in software design and testing in the team; there would also be a lot of Ops tasks that I can get involved in and enjoy doing. So we agreed for me to give it a try for a few months and re-evaluate.
And here I am, still in the same team after more than a year. And the interesting fact, which came as a surprise to myself, is that I’ve actually been really enjoying it. So I decided to share my experience here for those who might be in a similar situation, or those who haven’t considered joining a UI project.
In an ideal world, you would build features from back-end all the way to front-end as one team, and that’s the model we have tried here at REA in a number of projects with a team of individuals with mixed skills working closely together on both front-end and back-end tasks. Sometimes though, due to different reasons such as the size of the project, issues with team scale, or simply because the API hasn’t been built yet; you have to form a team only responsible for front-end, as we did for this project. Regardless of if it’s a front-end-only project, or a mixture of front-end and back-end, I think teams will benefit from back-end and front-end developers working more closely together.
What have I been enjoying doing in this project?
Never doubt your tech lead.
Many things about front-end development felt very different to my perception of it, which was based on my previous experiences in front-end projects. I'll cover some specific differences, which made this project very enjoyable for me in detail here:
- Arrow (lambda) functions - e.g.
array.map(x => x + 1)
- Array functional combinators (
- Classes - ES6 classes provide simple syntactic sugar over prototype-based OO and let you define classes very similar to how you do it in Java.
var- Block-scoped variables
I think if someone was to write an "ES6: The Good Parts" book, it would look like this in comparison:
ReactJS has been a major contributor to front-end development feeling similar to back-end programming for me in this project. My limited previous experiences with front-end development had involved:
- Writing HTML in a dynamic templating engine (e.g. velocity, mustache, etc.)
- Including sub-templates within parent templates
- Fetching data in a back-end language like Java
- Passing the fetched data to the top-level template and seeing variables get implicitly passed through to child templates
Some problems I've had with this approach are:
- Debugging how a piece of data used in a nested template gets passed down is usually very hard.
- Finding the linkage between DOM elements and event handlers is hard. They're in separate modules after all.
- Business logic and DOM manipulation code are usually mixed together. For example, the same event handler which sends a request to bookmark a listing, also adds a CSS class to an element to mark it as bookmarked.
I found that ReactJS addresses some of these issues for me and does even more:
Modularity and composability
In React, you define
props) and generate virtual DOM as output. Components can be composed by calling other components from the render method of a parent component.
UI templates and event handlers co-located
You can attach event handlers to DOM elements in the same
Component which renders the elements. This provides coherence and makes the impact of event handlers local, unlike event handlers applied using jQuery selectors.
Explicit passing of props
Props need to be passed down explicitly from each component to child components. Defining a variable in one template/component doesn't make it magically accessible to all child components (unlike Velocity for example).
One-directional data flow
boolean data attribute is passed as a prop to the component and used to decide if a "bookmarked" CSS class should be rendered. When the user bookmarks a listing, React’s
setState API is used to update the value. React then traverses the component hierarchy to determine which DOM elements need to be updated. No manual DOM manipulation code. Read more about this approach here.
There are more benefits to using ReactJS, but I'll leave it at that to keep this post short.
BEM and CSS Modules (a.k.a. sane CSS)
If like me, you've struggled with keeping the impact of your CSS changes contained to one element, don't worry; there are techniques and approaches like BEM and CSS modules to help you.
I'm not the best person to introduce BEM (Blocks, Elements and Modifiers) to you, but my naive understanding is that it defines rules and a structure for naming CSS classes to avoid clashes.
We've been using this approach in our new UI application. I overheard one of my colleagues explaining BEM to someone else like this:
BEM effectively provides a way to stop your CSS (cascading style sheets) from "cascading".
And isn't cascading the root of all evil?
More recently we've also started using CSS modules in some of our other UI codebases. I won't pretend that I can explain what CSS modules are, but if it does what it says (making your CSS modular), isn't it awesome?
Functions as first-class citizens
The recent introduction of arrow functions in ES6 has made it easier to define functions. This in turn makes application of functional programming techniques such as currying easier and more pleasant.
I hear you saying "but functions are useless without types". I've talked about types below.
We are all more or less familiar with different design patterns and have occasionally used them in back-end applications. Good news is that we've also been able to identify where it makes sense to use design patterns in our UI codebase and have successfully applied patterns such as decorators, adapters and strategies. We've also used higher-order components (a fancy name for a decorator) in a few places.
Due to functions being first-class citizens, we've been able to implement known Object-Oriented design patterns in much simpler ways. Many of the patterns implemented in our codebase are just simple functions. Much nicer than the scary class diagrams you’ll see if you Google design patterns.
- ReactJS component can declare prop types. These are only checked at runtime in dev mode or while running the tests.
Lots of things to learn
I mentioned earlier that one of my concerns before joining the team was that I felt overwhelmed by the number of things I had to learn to become an effective front-end developer. However, because of the excellent front-end developers in the team and across the company, I have been able to learn at my own pace. I can be confident that these knowledgeable people, who know how to "build UIs", are there to fill the gaps and help me to learn "how to UI".
If I go back to the list of UI things I thought I needed to learn, I can (shamelessly) say that I've only really managed to learn a few of them while I've been in this team:
And that's fine. I tend to think that I've been able to contribute to the project and the team with my back-end knowledge and experience.
Lots more you might enjoy doing in UI space
Opportunity to contribute to open source projects
Writing tech blog posts
There is a very large community of UI developers out there and again, given some of the tools used in UI space are fairly new, there is a big opportunity for publishing technical blog posts around things that you would be using in your day-to-day job.
Solving problems unique to UI
Perhaps closely related to my point on learning opportunities, there are a lot of challenging problems which are unique to UI projects, which you wouldn't have experienced in back-end development. If you're after a new challenge, you'll enjoy getting involved in:
- Web performance - Web performance is obviously a different kettle of fish compared to API performance. There is a lot to consider when it comes to performance of a web application, such as server-side vs. client-side rendering, size and number of asset files, lazy or eager loading of resources, code splitting (loading only what's needed for the current page), number of Ajax requests made, caching, third party code (we have a lot of them), etc.
- SEO - A concern fairly unique to UI applications. There are many interesting things to learn in this space.
- User experience
I still don’t consider myself a UI developer, I can’t do CSS for example or set-up a UI project from scratch; but I still found myself productive and have been able to contribute to our project. The point is you don’t necessarily need to know CSS or you don’t need to know a whole lot about HTML to make yourself useful in building a large UI application. There are always very good UI developers passionate about building UIs. You can pair with them and learn from them, while contributing your ideas from back-end. UI projects can definitely benefit from a close collaboration of developers with varied skill-sets.
And don't get me wrong. I don't mean to say that everything in front-end is shiny and perfect. Not at all. Having to deal with both null and undefined would still make you want to cry and
shrinkwrap will most likely break your heart on your first date, until you break up with them for
Despite some shortcomings, it's been a pleasant ride for me and I hope it will be the same for you.