Saturday, January 31, 2015

Deploying Static Sites on Google App Engine

Why Google App Engine?

1. Hosted on Google infrastructure, so it's going to be fast.
2. If it's a low traffic site, then it's almost free.

Steps

1. Python 2.7 must be installed on your machine. If you are on Mac, it's already installed.
2. Download GAE SDK for Python.
3. Create new application for your static site using GoogleAppEngineLauncher.
4. Create a directory called static under your-site-name directory.
5. Copy the following sample app.yaml for a static site:

application: essentialtdd
version: 1
runtime: python27
api_version: 1
threadsafe: yes

handlers:
- url: /(.*\.(appcache|manifest))
  mime_type: text/cache-manifest
  static_files: static/\1
  upload: static/(.*\.(appcache|manifest))
  expiration: "0m"

- url: /(.*\.atom)
  mime_type: application/atom+xml
  static_files: static/\1
  upload: static/(.*\.atom)
  expiration: "1h"

- url: /(.*\.crx)
  mime_type: application/x-chrome-extension
  static_files: static/\1
  upload: static/(.*\.crx)

- url: /(.*\.css)
  mime_type: text/css
  static_files: static/\1
  upload: static/(.*\.css)

- url: /(.*\.eot)
  mime_type: application/vnd.ms-fontobject
  static_files: static/\1
  upload: static/(.*\.eot)

- url: /(.*\.htc)
  mime_type: text/x-component
  static_files: static/\1
  upload: static/(.*\.htc)

- url: /(.*\.html)
  mime_type: text/html
  static_files: static/\1
  upload: static/(.*\.html)
  expiration: "1h"

- url: /(.*\.ico)
  mime_type: image/x-icon
  static_files: static/\1
  upload: static/(.*\.ico)
  expiration: "7d"

- url: /(.*\.js)
  mime_type: text/javascript
  static_files: static/\1
  upload: static/(.*\.js)

- url: /(.*\.json)
  mime_type: application/json
  static_files: static/\1
  upload: static/(.*\.json)
  expiration: "1h"

- url: /(.*\.m4v)
  mime_type: video/m4v
  static_files: static/\1
  upload: static/(.*\.m4v)

- url: /(.*\.mp4)
  mime_type: video/mp4
  static_files: static/\1
  upload: static/(.*\.mp4)

- url: /(.*\.(ogg|oga))
  mime_type: audio/ogg
  static_files: static/\1
  upload: static/(.*\.(ogg|oga))

- url: /(.*\.ogv)
  mime_type: video/ogg
  static_files: static/\1
  upload: static/(.*\.ogv)

- url: /(.*\.otf)
  mime_type: font/opentype
  static_files: static/\1
  upload: static/(.*\.otf)

- url: /(.*\.rss)
  mime_type: application/rss+xml
  static_files: static/\1
  upload: static/(.*\.rss)
  expiration: "1h"

- url: /(.*\.safariextz)
  mime_type: application/octet-stream
  static_files: static/\1
  upload: static/(.*\.safariextz)

- url: /(.*\.(svg|svgz))
  mime_type: images/svg+xml
  static_files: static/\1
  upload: static/(.*\.(svg|svgz))

- url: /(.*\.swf)
  mime_type: application/x-shockwave-flash
  static_files: static/\1
  upload: static/(.*\.swf)

- url: /(.*\.ttf)
  mime_type: font/truetype
  static_files: static/\1
  upload: static/(.*\.ttf)

- url: /(.*\.txt)
  mime_type: text/plain
  static_files: static/\1
  upload: static/(.*\.txt)

- url: /(.*\.unity3d)
  mime_type: application/vnd.unity
  static_files: static/\1
  upload: static/(.*\.unity3d)

- url: /(.*\.webm)
  mime_type: video/webm
  static_files: static/\1
  upload: static/(.*\.webm)

- url: /(.*\.webp)
  mime_type: image/webp
  static_files: static/\1
  upload: static/(.*\.webp)

- url: /(.*\.woff)
  mime_type: application/x-font-woff
  static_files: static/\1
  upload: static/(.*\.woff)

- url: /(.*\.xml)
  mime_type: application/xml
  static_files: static/\1
  upload: static/(.*\.xml)
  expiration: "1h"

- url: /(.*\.xpi)
  mime_type: application/x-xpinstall
  static_files: static/\1
  upload: static/(.*\.xpi)

# image files
- url: /(.*\.(bmp|gif|ico|jpeg|jpg|png))
  static_files: static/\1
  upload: static/(.*\.(bmp|gif|ico|jpeg|jpg|png))

# audio files
- url: /(.*\.(mid|midi|mp3|wav))
  static_files: static/\1
  upload: static/(.*\.(mid|midi|mp3|wav))

# windows files
- url: /(.*\.(doc|exe|ppt|rtf|xls))
  static_files: static/\1
  upload: static/(.*\.(doc|exe|ppt|rtf|xls))

# compressed files
- url: /(.*\.(bz2|gz|rar|tar|tgz|zip))
  static_files: static/\1
  upload: static/(.*\.(bz2|gz|rar|tar|tgz|zip))

# index files
- url: /(.+)/
  static_files: static/\1/index.html
  upload: static/(.+)/index.html
  expiration: "15m"

- url: /(.+)
  static_files: static/\1/index.html
  upload: static/(.+)/index.html
  expiration: "15m"

# site root
- url: /
  static_files: static/index.html
  upload: static/index.html
  expiration: "15m"

6. Click deploy on GoogleAppEngineLauncher.

Since I bought my domain using Google domains, I configured custom domain to point to my GAE instance by using the Google Developer Console and Google Domains account page as follows.






References

1. Free Static Website Hosting on Google App Engine
2. Google App Engine to Host a Static Site
3. Google App Engine Concole
4. Configuration file

Friday, January 30, 2015

Explicit Use Case Representation in Rails Apps

Here is the notes from my Silicon Valley Ruby presentation:

Opening

Object Oriented Programming promised us re-use and ease of maintenance. OO paradigm delivered on re-use but not on ease of maintenance. Hi, I am Uncle Toni, the rest of the presentation is about how we can overcome the limitation of Object-Oriented Paradigm.

Middle

Ease of maintenance? How? It is relative. When compared to procedural languages, yes. But, this is 2015. We need to be able to quantify the ease of maintenance claim. Given a requirement, can we estimate and come up with how many weeks it will take to finish? Your manager comes to you and asks how long a new feature will take, how do you answer that question?

What do you do to find out the level of effort required to finish the feature on time? You read the Wiki, which is out of date and in sync with the current code base. You read the code. You don't know how the code works. So you talk to the developer who wrote the code. There are communication issues. I cannot estimate unless I have an understanding of the system.

How do we gain an understanding of the system? Can tests help? Cucumber features does not provide trace-ability. Because, the steps create and call methods on it. We cannot get a big picture view of the system that helps us to estimate. It introduces accidental complexity. Bob Martin's suggestions result in bloated code and over-engineering. We don't want Repository pattern and all that Java crap that becomes a heavy burden.   

Let's imagine an ideal world where we are not restricted by any programming paradigm. What does the ideal solution look like? We need a trace-ability matrix that shows which use-cases map to which class and methods. Some of the classes are re-used by more than one-use case so we have some reuse of code. These shared classes are called tangling. The wide spectrum of classes that collaborate to achieve a high-level use case is called scattering. The use-cases are cross-cutting because they cut through different layers of the system. 

In a well-designed system we have layered architecture where we separate the view, the controller and the persistence layer. This allows us to allocate work according to the strength of a developer. As long as we obey the contract between the layers, teams can work in parallel.

How much time do you think you spend on maintenance as a developer? Microsoft did a survey and found out that 90% of the developer time is spent on maintenance. If you reduce that by half, you can save 50% of your maintenance cost.  

Ideally I want to glance at the code and instantly know which part of the code has the use case that my manager is talking about. Read my blog post on why using interactor gem is a bad idea.

I don't use Rails filters for business logic. It is very difficult to reason about the code. I thought only others write bad code. I consult for start-ups, I see code written by inexperienced developers, find missing abstractions. Make the view dumb, thin controller and fat models. Then I realized the projects that I developed from scratch, after a few months when I saw the code base, I had 'WTF' moments. What was I thinking? When does this thing get called? Is it even used anywhere? Can I delete it? How do I use this feature?

Why Not Use Tests for Traceability

People get very clever in tests. Ideally, I want to see 'Once upon a time, lots of things happen, then they lived happily ever after'. The tests does not tell me a story. Here is the link to my solution that aims to be a trace-ability matrix. Maybe one of you can create a gem that will analyze the code and create a nice matrix. This matrix can be kept in sync with the code because it is generated by analyzing the code. It be part of the build system, where a post-checkin hook can get it gets published to the wiki automatically. You can use this as a starting point to do impact analysis. What is the impact of this new requirement? How many classes and methods will have to change? Based on that you will get an idea of the complexity of the new requirement. 

Question from the audience after browsing my code above. Why not put all the uses cases for an actor into the same file? 

Because the only thing I liked about the Interactor gem is that when you open the interactor folder you get a list of all use cases, it shows what the system can do. I don't like the fact that the class names are verbs. Ideally, you want the class names to be noun and the method names to be a verb. I have seen interactor gem more often being abused in the projects that I have been involved. I also think naming the classes with the verb as breaking the basic OO design principles. If you are hitting the limits of OO paradigm, then you need to think about other ways of solving the problem. 

When a failure happens, you have to fail loudly. That means raising an application level exception. The reason is that it is extremely difficult to hunt down bugs that are hidden behind some code that is failing silently. I have spent weeks to find these kind of bugs. If you see the home page of interactor gem, you will see they are checking for a flag to check for success/failure. 

I also don't like the proliferation of so many classes with just one method. Why do we need a class for each step in a use case? It does not make much sense to me.

Possible Solution

Luckily Ruby allows the file name for a class to be anything. So we can have the file name named after the use case name. 

I read the Ivor Jacobson's book Use Case Oriented System written in the 1990's. He talks about describing the use cases that is agnostic of the technology. When a developer works with the use cases, the use cases needs to be converted to objects with responsibilities. Even if you have no semantic gap between your code base and the use cases, you still have a mismatch between the user's perspective and the developer's perspective. You might have concepts in the code that does not have any counter part in the use case or the domain. 

BDD does not mean using Domain Driven Design. DDD is about using aggregates, entities, architectural patterns and so on. It's not just using the terms used in the domain.

One of the paper I read uses Django framework and uses complicated solution where use cases are store in a repository with use case annotation to achieve trace ability. I don't want to over-engineer and complicate things. Non-invasive tools would be better, where I can run a gem like Rails best practices and get a nicely formatted trace ability matrix.

Can DCI architecture address these problems? What if Ruby 3.0 came up with a new language construct? My solution has an entry point into the system, it does not do any work by itself. It delegates all the work to other objects. It orchestrates the entire use case. 

Note for myself: Take a look at concerns and see if you can get rid of the require statements in application.rb.

TDD is Dead Episode 1 Concise Version

David's three major issues with TDD and Unit Testing:
  1. Confusion over the definition of TDD and unit testing, 
  2. Test-induced damage through using mocks to drive architecture
  3. How the red/green/refactor cycle of TDD never worked for him. 
Kent said that programmers deserve to feel confident that their code works, TDD is not the only way to reach that.

David agrees that you're not done till you have tests. But doesn't like TDD as a way to get there. He thinks people have different brains and thus like different techniques, he doesn't like that TDD gets conflated with the confidence you get from writing the tests first.

Kent agrees that there are cases where TDD is not suitable. In the TDDable code he found he was in an enjoyable flow, but found the other part more tricky. But in the non-TDD part he still used regression tests and short feedback loops. He has no problem mixing both styles. TDD reminds him of how he learned mathematics at school - always needing examples.

David has been in situations where TDD flowed well, but most of his work isn't like that - his question is what are you willing to sacrifice to get that flow? Many people make bad trade-offs, especially with heavy mocking.

Kent said he rarely uses them, he's concerned that those that do mock often find refactoring difficult, while he finds testing makes refactoring easier.

David said his reaction was to seeing people describe TDD in a mock-heavy style as a moral thing to do and the result was a lot of code that was poorly designed due to its desire to enable isolated unit tests.

Next episode will explore how TDD may lead to design damage. This is the concise version of the transcript of the video : Is TDD Dead?

Wednesday, January 28, 2015

How to download an entire site to your machine


1. brew install wget
2. wget --recursive --no-clobber --page-requisites --html-extension --convert-links --domains somedomain.com http://somedomain.com/index.html

--domains flag indicates don't follow any external links from somedomain.com site.
--recursive flag tells wget to download all the files on that domain
--page-requisites - get all assets (images, CSS etc)
--html-extension : save files with the .html extension
--convert-links : convert links so that they work off-line
--no-clobber : don't overwrite any existing files


Wednesday, January 21, 2015

Top 10 Reasons Why Test Driven Development in Ruby Course is Awesome

Test Driven Development in Ruby Course is a comprehensive online course that covers the basics of Test Driven Development in Ruby for beginners. This course aims to help beginners to overcome difficulty in learning TDD. Each lessons in the course has hands on exercises to reinforce the material. You will learn TDD by applying the concepts in the lessons. At the end of the class, students will have worked through some common interview problems and gained skills that can be used to answer questions in an interview.
TDD in Ruby
  1. This course is designed by a developer for developers
  2. It makes complicated concepts easy to understand
  3. It is hands on step-by-step guide to learning TDD
  4. It gives a solid foundation for a beginner to TDD
  5. You will be doing Test Driven Development in Ruby in less than 4 hours
  6. Access to the entire transcript that is not released to the public yet.
  7. Access to the transcript in audio form that is not released to the public yet.
  8. Lifetime access to 42 lectures and 8 quizzes
  9. 3.5 hours of high quality content
  10. Use the downloadable checklists to guide you when coding
This course is the result of teaching one-day TDD boot-camps and TDD tutorials for Silicon Valley Ruby Meetups. I have spent more than 500 hours and thousands of dollars to create this course. Click on the image below to enroll for this course now.


TDD in Ruby

TDD in Ruby