Skip to content
This repository has been archived by the owner on Oct 8, 2019. It is now read-only.

2nd iteration of BI SP1

Honza Bittner edited this page Apr 21, 2018 · 10 revisions

Technology selection

We have written about why why we have chosen given technologies in 1st iteration report. Now, there is time to evaluate if the selection was good, bad, and describe pros & cons.

Dart, Flutter and AngularDart

Our language for the whole project, the Dart language, was definitelly a good choice. The language is similar to what we know—Java, C++, C#, …—and therefore we can code and don't spend time with fixing syntax nonsense. The language is modern and has a very nice APIs.

Flutter and AngularDart, very interesting technologies around the Dart language. Both technologies are in active development and therefore things my change over time, which is neither always bad nor good—it simply has it's pros and cons. With Flutter, which is now in beta, wasn't problem at all, except of number of missing tutorials we could have used to learn. Flutter is nice, funny and easy-to-learn technology, we are very glad we have chosen it! Some of us have a bit of experiences with Android development, both in Java and Kotlin, or in things like PhoneGab, and we cannot say we liked it. Flutter <3

We have might do a small mistake with using newest AngularDart, because it's very, very different from older version. One of us worked in AngularDart in a job and this version is very confusing even for him, because of the lot of changes in workflow, APIs, life cycles, ...

Cloud Firestore

Cloud Firestore, especially on Flutter, provides an amazing API to work with! It keeps local states, does synchronization, ... Only disadvantage I can see is absense of some search (LIKE-alike, contains()-alike) functions. I understand it works a lot with indexes and therefore it only know ==, !=, <, <=, > and >= operators. Only one step to perfection. For our little application, those are no issues, but for bigger apps, which have to download a ton of data, custom search (e.g. download everything and search in it in the production app) might be very expensive process.

GitHub

We have thought the best choice for team management is GitHub—and you know?, we was right! It has awesome tools for git, it has awesome tools for issue (task) management. Everything is connected which makes a nice sense to me. 10 points for GitHub!

Discord

We hadn't been sure what comunication tool to use. We could had use Slack, but that is something we already knew. We also had known Discord a bit, as a new Slack-alike platform for gamers, streamers etc. And because it's free plan, where are voice, video calls included, we decided to chose it. We did also set up GitHub webhooks, so we have a nice feed.

The platform has a lot of issues, or maybe I should say thing to improve. But we have everything for free—chat, voice, video.

What we have learned

This technology is young, active and it changing

In the meantime of our development, Dart 2 was released for Flutter, new build tools was released and with all that, also Flutter went from alpha to beta version.

Also, there is a new AngularDart v5, which works on top of the new build tools, has a new concepts of routing, bootstraping app etc. A lot of things works now through "templates", which are generated files from your code. It's very different from previous version, but I see what authors wanna do. And I kinda like the approach they have.

That is a huge breach in our study and in our work. The progress is good, but the adaptation is not always as fast as we would like it to be.

Support from Dart world on Gitter

Flutter is a young project and it's still in beta. There are not much tutorials out there either. So what to do if you got stuck in middle of some issue?

Flutter community is very active on Gitter and they are willing to help you with your problems. And we did help too! In the time of developing, we got stuck a lot of times, mostly because we don't have much experiences with mobile development, so we don't know how to do things. Sometimes we just used the wrong version (old, different branch, ...) of Flutter framework. Anyway, the Flutter comunity will help you most of the times, that's the point of this paragraph. And that is amazing!

Authentication

One of the biggest issues in this project was setting up the authentication, we have chosen the google account authentization. Because of the evolving of the Flutter framework, we have spent the whole day trying to accomplish it to work and after the whole day, we have discovered that it doesn't work in the beta channel of the Flutter framework. After switching to the master branch, everything magically started to work.

I do not know what is worst, that we spent a whole day trying to set it up, or that the fix was so easy... #nopainnogain

Localization is not easy to set up

Another magnificent thing we had to dealt with is localization. We simply wanted to be able to switch languages of our UI, at least between Czech and English. And if you have never done localizations, trust me, it will be very, very paintful.

The whole process of it is not easy to understand, at least not for us. We have spend a whole week trying to set it up correctly and trying to split it well, so we can share as much as possible betweet applications.

We have written scripts to help us with that and at the end of a day, it's seems like a very easy workflow, but the starting with it—paintful.

We have chosen a way with .arb files, because they are pretty common in open source projects. The whole workflow works like this: in your app, you have to set (request) the translation, from those requests—we keep them in one file in static methods—the arb files are generated. After translating arb files, which are the real translation source, they are generated to another Dart files which contains the output from that arb files. It's still a bit tangled for me to orient in it how it works, but it's working.

How widgets works

The Flutter has a interesting concept and we have to follow it's cycle to keep everything in order. We think each widget should follow some conventions, even in method order. For us, the best way to work is probably this:

  1. properties (variables)
  2. initState()
  3. dispose()
  4. build()
  5. _build* methods—methods which returns widgets and are used as shortcuts of build() methods
  6. other methods

Unlike of Angular, in Flutter there is no globally managed state of widgets, which means, that every change (rebuild) of widget has to be manually called by programmer. This is a big speed improvement. Also, there are two types of widgets—StatelessWidget ("const"/"final" widgets; simply widgets with no state updates) and StatefullWidget which can change state by calling setState(() { ... }) method.

The concept is something now, for us, web and console app developers. But we used to it pretty quickly. We had no chance, to be honest—if you do it wrong, it will not work.

initState()

Initialization method, somehow similar to constructor.

dispose()

Dispose method, somehow similar to descructor.

build()

The most important method of all. In this method, all drawing is done. The build method might be somethimes very big, so it's a good practise to don't repeat yourself and outsource parts of code in separate _build* methods.

Logical architecture design

In order to use the whole platform to maximum, we share code across the application. In our application, we use something called BLoC—Bussiness Logic Component. By following it's rules with no excuses we are given very solid structure for our application logic. Because of this, we have separated logics (we share everything), apis (we share common interfaces, inplementations are dependent on platform) and views.

We think using BLoC in our project is very beneficial, because it's simple and we can share code very well.

BLoC designing guidelines:

  1. Inputs and outputs are simple Streams/Sinks only
  2. Dependencies must be injectable and platform agnostic
  3. No platform branching allowed
  4. Implementation can be whatever you want if you follow the previous rules

UI design guidelines:

  1. Each "complex enough" component has a corresponding BLoC
  2. Components should send inputs "as is"
  3. Components should show outputs as close as possible to "as is"
  4. All branching should be based on simple BLoC boolean outputs

TL;DR

  1. Move bussiness logic to BLoCs
  2. Keep UI components simple

App prototype

Langing screen

On aplications start, the app logo animates and user can login into the app using the Google account. If user have already used our application, the login process is done silently.

mobile

web

Main screen

The main screen contains 3 tabs which filters courses:

  1. all courses
  2. courses created by me
  3. all courses sorted by popularity

mobile

web

Navigation

Every major screen in our app has a navigation. Using the navigation, user can use the app and changes screens. It is also possible to sign off and report bug using the navigation's buttons.

Search screen

On search screen, user can filter courses and find the desirable one by it's name.

Course screens

The courses contains description, sections, materials and sets of playing cards.

mobile

web

About screen

About screen informs user about our app, our development, provides a bunch of useful links and shows licenses.

Licenses screen

You can get to the Licenses screen from the About screen. This screen is automatically generated.