Working with Postgres from the development environment
Our industry is dominated by the shape of our tools. Our tools shape the way we think and due to their design, they often lead to artificial silos.
Let’s take an example: database tools are perceived to be different than the typical tools from an IDE, and this correlates with how we see working with a database as being different from typical programming. Yet, this does not have to be like this.
The picture below shows how we transformed Glamorous Toolkit into a database exploration tool: on the left, we have a Playground with a snippet that allows us to inspect a client over a database connection. The client Inspector allows you to enter SQL, and you see the result as a table.
All this is happening in the development environment following the inspection workflow.
The inner makings
The tool is the visible effect. The essence of moldable development is to empower developers to customize the environment for their own system. That’s why it’s interesting to peak behind the scene to get a sense of what molding the Inspector entails.
The P3 client that connects Pharo with the Postgres database was already implemented by Sven VC. In this post we discuss how we adapted the environment to that library. There are several pieces that are involved in this tool. Still, the overall cost of molding the environment is literally measured in a few dozen lines of code.
The panes to the right show two inspectors, one on an instance of a
P3Client and one on an instance of
P3Client inspector shows a view for SQL. That view is an extension that is defined in the following way.
^ aView textEditor
text: [ '' asRopedText monospace ];
actionButtonIcon: BrGlamorousIcons playinspect
action: [ :aButton |
| query result |
query := aButton phlow textViewContent asString.
result := self query: query.
aButton phlow spawnObject: result ]
We have a
SQL, that has an empty text and that offers an action. The action logic essentially takes the text and invokes the
query: on the client.
The view is defined as a method of the
P3Client and its implementation can be observed, and even be modified, directly in the Inspector by
Alt+clicking on the view tab.
P3Result offers a table view.
| columnedList |
columnedList := aView columnedList
items: [ self data ].
self columns doWithIndex: [ :column :index |
columnedList column: column fieldName do: [ :aColumn |
item: [ :eachRow | (eachRow at: index) ];
matchParent ] ].
To start the workflow, we need to get the
P3Client instance. The above picture shows a form snippet with a button than when pressed produces the initialized instance. The snippet is the most expensive part of our tool because it requires a class that defines the fields and the form. However, that snippet is equivalent to writing code in Pharo as shown in the picture below.
This is a good example for how a tool can be built incrementally where each increment adds value at a small associated cost.
Exploring database schemas
A database client also knows how to retrieve the schemas from a database. Schemas contain tables with dedicated structures. With a few extensions, we can make the Inspector navigate these as well.
Our industry is dominated by the shape of our tools. We have to take control of that shape.
A database tool is perceived to be different from other development tools. Yet, the tool presented here shows that working with a database can be treated like any other inspection workflow. In other words, there needs not be a difference between the database and the programming tools. And if there isn’t a difference, there are no silos. Instead, the two worlds are combinable to form new workflows in a seamless continuum.
The tool support presented here is rather simple. Yet, the cost is small as well. Furthermore, even if the resulting tool is small, it could still further be split into smaller parts, each of which was built in minutes and each of which added value. This opens up a whole new way of dealing with tools. That is the essence of moldable development.