|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- title: Building Large Flask Apps In The Real World
- url: https://etscrivner.github.io/posts/2014/10/building-large-flask-apps-in-the-real-world/
- hash_url: 23a57db93ad36a37f40e1ff30b5dea2d
-
- <p>Scaling a <a href="http://flask.pocoo.org/">Flask</a> application is no immediately obvious
- matter. At plug.dj we had ~22,000 line Flask application. At my previous
- employer our Flask application was significantly larger. Ultimately scaling a
- code-base is less about the framework used and more about the software design
- experience of the developers working on it. Scaling in terms concurrent users
- also has little to do with the web framework and more to do with your
- understanding of load-balancing, caching, databases, etc. That being said, what
- have I learned about how to organize a Flask application to comfortably grow?</p>
- <p>Firstly, <a href="https://github.com/imwilsonxu/fbone">fbone</a> and
- <a href="https://github.com/cburmeister/flask-bones">flask-bones</a> are great first
- approximations. If you're struggling to figure out how to structure your flask
- application have a look at those and consider using either one as a template
- that you can evolve to your needs. Also, I have to mention
- <a href="https://github.com/audreyr/cookiecutter">cookiecutter</a> as a tool for templating
- the structure of python applications in general. In terms of the web application
- itself you might also consider using
- <a href="https://pythonhosted.org/Flask-Classy/">Flask-Classy</a> to build out your views.</p>
- <p>Beyond that I hestitate to dictate anything else. There's never a
- one-size-fits-all solutions for complex real-world problems like this. There
- will never be a substitute for thinking up-front, and deeply at that, about the
- organization of your application. The first few organizational decisions will
- have ripple effects throughout the lifetime of the code base. Bad decisions can
- trap you into a corner. Good decisions can make previously difficult problems
- much easier. So instead here are a few heuristics that I've used to kickstart
- this process:</p>
- <ol>
- <li><strong>Think about deployment</strong>. How is it getting to the server? egg, wheel, rpm?
- Will there be <a href="http://jenkins-ci.org/">continuous integration</a>? Are you using
- <a href="http://www.saltstack.com/">salt</a> or <a href="http://www.puppetlabs.com">puppet</a>? How
- you deploy your application will determine what kind of structure you need
- and what kind of supporting utilites you may or may not have to write.</li>
- <li><strong>Think about app initialization</strong>. Where is the entry point? How are
- components initialized and shared? If my user module needs a database
- connection how do I ensure that it always gets an initialized database
- connection? Do I use singletons? lazy loading? dependency injection? It
- depends, and you should always be willing to revisit this decision. Also
- think about how you'd do a deploy to a completely uninitailized environment.
- How do you initialize the database(s)? Is the app configured by environment
- variables or cfg files? How are those being shared and deployed?</li>
- <li><strong>Think about resource lifetimes</strong>. Make sure you understand how your
- database connections and other resources should be managed within a Flask
- application. Typically you should initialize a resource when a request comes
- in and tear it down before the response goes out. SQLAlchemy
- <a href="http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#using-thread-local-scope-with-web-applications">explicitly covers</a>
- integration with web frameworks in its documentation.</li>
- <li><strong>Organize by principle of least suprise</strong>. Ask yourself, "How would I
- organize this so that someone using Notepad with a good grasp on the
- programming language would be able to find and edit any arbitrary component?"
- This is ultimately how your codebase will seem to every new person who
- encounters it. For example, if you are asked to modify the function that
- geocodes a location and you have no experience with a code base it's
- reasonable that you'd look in <em>app.geolocation.utils</em> as a first
- approximation. You'd be suprised if instead it were somewhere like
- <em>app.auth.models</em>. The first example follows the principle of least surprise.
- Reduce the mental strain on yourself and others by sensibly organizing
- components into well named modules.</li>
- <li><strong>Think about testing</strong>. A focus on testing can help you avoid sticky designs
- because they simply become untestable. Organize your tests along the same
- lines as your modules so that the corresponding tests for any chunk of code
- can easily be found.</li>
- <li><strong>Think about logging</strong>. Bugs are going to happen and you're going to need to
- gather the information to solve them. Come up with a logging strategy that
- covers your whole application and stick to it. You should be able to log data
- from anywhere in any module and the logs should indicate exactly where the
- data came from. In Python the best way to do this is to initialize a logger
- at the top of each .py file, that way you always have access to a logger from
- every module.</li>
- <li><strong>Think about infrastructure changes</strong>. One of the best design heuristics you
- can use is to imagine how you would build your application so that arbitrary
- third-party dependencies (databases, web frameworks, etc.) could be swapped
- out with minimal impact. As your application grows your infrastructure will
- change. You should be able to switch databases, web frameworks, or deploy
- code to mobile devices with minimal code changes. A good place to start in
- figuring out how to do this is the
- <a href="http://confreaks.com/videos/759-rubymidwest2011-keynote-architecture-the-lost-years">Architecture The Lost Years</a>
- talk by Bob Martin.</li>
- </ol>
- <p>Each of these topics could easily fill a blog post on its own. With Flask in
- particular (2), (3), and (6) are crucial. Flask isn't like Ruby on Rails for a
- reason. Flask is designed to be easy to get up and running. It also puts you
- closer to WSGI. This, however, is a double-edged sword. It can make development
- easier in areas where you know what you're doing while also making it easy to
- shoot yourself in the foot in the areas where you don't.</p>
- <p>In the end you should be aiming to design your application to depend on Flask as
- little as possible. The framework shouldn't dictate your application design, and
- microframeworks in particular try to avoid doing this as much as possible.
- Recently even Flask has felt bulky. <a href="http://falconframework.org/">Falcon</a> seems
- like a good step in the direction of something smaller.</p>
|