You can load the solution of the previous week using the following snippet:
Then, you can browse the code of the TBPost class.
With this solution, you can complete the code of your TinyBlog application if needed before continuing.
50.2. Save your code
Even if you can save the Pharo image which contains all the objects of the system
(and as such the classes you wrote), this section explains how Pharoers usually save their code as packages on dedicated servers with the Pharo versioning system named Monticello. Smalltalkhub http://smalltalkhub.com is one of these servers to host saved Pharo code. You can also use SS3 at http://ss3.gemstone.com.
Create a project (it may happen that you get a connection problem because the web site is still in beta, in such a case retry with a different web browser. If the problems persist use http://ss3.gemstone.com).
Name it the way you want. For example "TinyBlog"
50.2.2. Save your package
In Pharo, open the Monticello Browser available in the main menu.
Add a repository (of type either SmalltalkHub or HTTP for SS3)
Select the repository and the menu item 'Add to package...' to add this repository to the package TinyBlog.
Select your package and press the 'Save' button.
Enter a log describing the changes you did.
The code of your application is now in your SmalltalkHub repository. You should now be able to load your code in a new Pharo image. Nevertheless, if you use a stock Pharo image, you must also load Seaside and other libraries and frameworks.
In this project, we encourage you to always use the image we gave with the preloaded packages and that you can find at http://mooc.pharo.org. This will let you load new code without having to take care about package dependencies.
50.3. About dependencies
Good practices in Pharo developments are to clearly specify the dependencies of used packages. The idea is to ensure that the building of a project is fully reproducible.
It is important because once we have such reproducible process we can take advantage about automatic build servers such as Jenkins or Travis.
To express dependencies between projects and packages within a project
Pharo offers special classes called Configurations. Such configurations express the architecture (main repository, dependencies to other projects, structure of the projects) as well as versionned packages.
In the context of the TinyBlog project, we do not got any further on this. Note that a full chapter on dependency expression is available in the Deep In Pharo book.
50.4. TBBlog class
A TBBlog contains posts. We will now develop this TBBlog class and its unit tests.
We initialize the posts to hold an empty collection.
50.5. Only one blog object
In the rest of this project, we assume that we will manage only one blog. Later, you may add the possibility to manage multiple blogs such as one per user of the TinyBlog application.
Currently, we use a Singleton design pattern on the TBBlog class.
Since all the management of a singleton is a class behavior, we define such methods at the class level.
50.6. Testing the Model
We now adopt a Test Driven Development approach i.e., we will write a unit test first and then develop the business functionality until the test is green. We will repeat this process for each functionality of the model.
We create unit tests in the TBBlogTest class that belongs to the TinyBlog-Tests tag. A tag is just a label to sort classes inside a package (See menu item 'Add Tag...'). We use a tag because using two packages will make this project more complex. However, while implementing a real application, it is recommended to have a separate package for the tests.
Before each test execution, the setUp method initializes the context of tests.
For example, it erases the blog content, adds one post and creates another temporary post that is not saved.
As you may notice, we test different configurations.
Posts do not belong to the same category, one is visible and the other is not visible.
At the end of each test, the tearDown method is executed and resets the blog.
Here we see the limits of using a Singleton. Indeed, if you deploy a blog and then execute the tests, you will lose all posts that have been created because we reset the Blog singleton.
We will now develop tests first and then implement all functionalities to make them green.
50.6.1. First test
The first test adds a post in the blog and verifies that this post is effectivly added.
If you try to execute it, you will notice that this test is not green because we did not define the methods writeBlogPost:, removeAllPosts and size. Let's add them:
The previous test should now pass (i.e. be green).
We should also add tests to cover all functionalities that we introduced.
50.6.2. Test the number of blog posts
50.6.3. Remove all posts
50.7. Other functionalities
We now develop new functionalities as methods in the 'action' protocol of the TBBlog.
While doing that, we regularly ensure that tests pass.
50.7.1. Retrieve all posts (visible and invisible)
50.7.2. Retrieve visible posts
50.7.3. Retrieve all posts of one category
50.7.4. Retrieve all visible posts of one category
50.7.5. Check unclassified posts
50.7.6. Retrieve all categories
50.8. Possible extensions
Many extensions can be made such as: retrieve the list of categories that contains at least one visible post, delete a category and all posts that it contains, rename a category, move a post from one category to another, make (in)visible one category and all its content, etc. We encourage you to develop some of them.
To help you testing the application, you can add the following method that creates multiple posts.
If you inspect the result of the following snippet, you will see that the current blog contains 5 posts:
50.9. Conclusion
You get now the full model of TinyBlog as well as some tests. You are now ready to implement more advanced functionality such as the database storage or a first HTTP server. Do not forget to save your code.