Google’s Material Design

At Devoxx 2014, a large amount of presentations involved Google’s Material Design and Polymer. Before we dive into Polymer, it might be useful to have a look at some of the design guidelines proposed by Google. These guidelines are bundled into a style guide, named Material Design.

What is Material Design?

Material Design is a set of guidelines that are useful for modern designers. These people are challenged with the daunting task to create a design that not only targets desktops, but also the web and mobile devices. These are totally different applications, sometimes being developed by different teams. To make the user experience intuitive and consistent over these multiple platforms, a strict set of rules need to be defined.

Google’s Material Design consists of two components: material and motion. The material component provides context in design. It’s the surface and elements that are visual to the user. Material also acts in a certain way. For example, material can cast shadows. These real-life properties of materials are included in the guidelines for an intuitive look and feel.

The motion component makes sure that there is some kind of continuity in your product. Animations are supposed to give meaning to your actions. The user experience should be fluent and uninterrupted.

material-design-1

Material

In material design, material has a lot of properties. First of all you will need to grasp that material design is a 3D world that is displayed in 2D. Each material and component has a width, height, but also a thickness (1dp). This thickness allows the material to cast shadows, and by animating these shadows, the designer can make the 2D material move over the z-axis.

material-design-2

Guidelines for color and typography will make your important content stand out. It will allow the user to make a bold statement.

material-design-3

Components

Material design not only shares guidelines for high level principles, it also defines guidelines for specific components. Google also implemented these guidelines in an open source framework called Polymer. We’ll have a closer look at some of these components.

Buttons

There are three different types of buttons. The most iconic one is the Floating Action Button (or FAB short). This is a button that represents the most logical action in the current context (for example: the add-functionality when you are in a calendar application).

material-design-4material-design-5material-design-6

Cards

This material can be used as a viewport and as a dialog. You can make a collection or grid of cards in your applications to show a more visual type of list.

material-design-7

Lists

Material Design also covers lists. A list consists of a single continuous column of sub-divisions of equal width called rows. These rows hold content and can vary in height. These lists are best suited to display a homogeneous data type or sets of data types.

material-design-8

Conclusion

Google’s Material Design is a goldmine when you are looking for modern design information that is applicable across different platforms (mobile/web/desktop). The comprehensive guide is a must read for everyone that are developing layouts and designs.

The properties of material and motion reflect the realistic world and that’s why these interfaces look and feel so intuitive. Being optimized for touch, these designs are set for the future.

If you are looking for an example application that uses the guidelines of material design, Google’s example quiz-app topeka is a great showcase for Material Design, Polymer and Paper Elements.

5 Minute JavaScript #11: Prototypes

Last week, we discussed the JSON format. Today we are going to take a deeper look in the object structure in JavaScript. In most object-oriented programming languages you have some kind of classical inheritance. This means that the language allows you to define a sort of blueprint of an object named a class. JavaScript doesn’t work with these concepts. Instead, it works with prototypes. The dynamic nature of JavaScript allows you to apply inheritance on object level instead of class level. Every object has a prototype object, you can set this prototype object and automatically you will be able to access properties or functions on the child object.

var parentObject = { x:1, y: 1 };
var childObject = { x: 2, a: 2 };
childObject.prototype = parentObject;

In the example above, the childObject has three properties: x, y and a. Whenever JavaScript is interpreted, the interpreter selects the first instance it finds of a property/function. So if we would look for the property x on childObject, we would find 2 instead of 1 because the childObject’s x definition is the first one the interpreter encounters.

In JavaScript native types also have a prototype object. That prototype contains all the methods you can use on the type. For example the String type has a prototype object that contains the following methods:

  • String.prototype.charAt()
  • String.prototype.slice()
  • String.prototype.trim()
  • String.prototype.split()
  • String.prototype.toUpperCase()

These prototype methods are easy to use, you can just call them from the object, e.g. “lowercase”.toUpperCase(). Not only the String type has these methods, also Object, Array, Number and even Function!

var char = 'my string'.charAt(0);

We use these prototype functions every day and the fun thing is that we can create our own. But that’s for the next blogpost.

5 Minute JavaScript #10 JSON

This week we’re taking a break from complex code structures (like modules in the previous issue) and we get back to basics. JSON is a lightweight data-interchange format. Easy to read/parse but also to write/generate. It’s related to the way we notate objects in JavaScript, that’s why it’s called JavaScript Object Notation. Visit the website: http://json.org/ for complete information about JSON.

An example of a JSON object

{
    "str": "string",
    "bool": false,
    "obj": {
        "arr": [ 1, 2, 3, "string", false ]
    }
}

JSON is a popular way of formatting data when dealing with REST services. Whenever you are generating data (at REST level at the back-end) for web applications, you know that your data will be read and parsed by JavaScript. What better format for JavaScript to parse than its own object notation? This is why JSON is such a great way to interchange data. It’s lightweight, fast, easy, readable…

There are also some useful tools that you can use regarding JSON. http://jsonlint.com/ for example checks if your JSON-string is formatted correctly. http://json-schema.org/ describes your JSON-object in a way very similar to XML-schemas.

5 Things I wish I knew about APEX when I just started (part 2)

In my first post of this series, I talked about subscriptions. The next post in this series is about cookie sharing in APEX, I hope you enjoy it.

Apex SSO by Cookie sharing

In the spirit of the previous post, this post will also be one that comes in handy when running multiple applications in the same workspace. When running multiple applications in the same workspace, it’s possible to share the authentication across multiple applications so you don’t have to login every time you switch applications. The only problem is that the feature is tucked away pretty good in the authentication scheme settings.

First we will Create 2 standard Applications

Untitled-1

Now we will create a simple page with a link to a page in the other application, to test if our setup works.

Untitled-2

If we would click the link now we would be redirected to the login page of the other application since, we’re not yet authenticated.

Untitled-3

What we need to do now is set up our authentication, to keep it simple I will make a hardcoded function where the process checks for username and password admin. But feel free to use your own custom login procedure. :-)

Untitled-4

Now for the important part, scroll down in the authentication scheme until you see a block called “Session Cookie Attributes”

In the cookie name field, you can set a name for your cookie, the important thing for this to work is that the name is the same in both applications, you also have the option here to define extra settings for your cookie. Whether it should be secure or not and the cookie path and domain.

Untitled-5

In the second application create the same authentication scheme as a copy of an existing authentication scheme. You can subscribe the authentication scheme to the first application.

For more information about subscription you can look at my first post.

If we log in to one of our applications now, we should be able to switch applications by clicking on the link we have created

That’s it! The third blog in this series will be about build options, click here to read it.

.

5 Minute JavaScript #9 Module Design

In issue #8 we learned how we could create a framework with a closure and return object. We can extend this template for creating modules for a previously defined framework or parent module.

By modifying the framework template a little bit, we can create a module that plugs into another object.

(function (parent){
     var name = 'module';
     var version = 1;
     if (!parent[name] || parent[name].version < version) {
          parent[name] = function () {
               // Private members
               return {
                    version: version
                    // public members
               };
           }();
     }
}(Framework));

In the example above, we create a module with a certain name and version. We check if the parent (in this case Framework) doesn’t contain the module, if it does… we check if this is a newer version. Note that you can add your own versioning system to this declaration of modules, this is merely an example.

Instead of passing along the Framework, we could feed the closure Framework.module. The code will stay the same, but instead of creating a module on framework (with checks), we will create a sub-module.

By using a simple pattern (closure + return object) we are able to create frameworks, modules, plugging them into frameworks or other models. Also, we can hide functions/variables from outsiders and we choose explicitly which functions and variables are available.

A JavaFX 8 Stock Ticker application

Since Java SE 7, update 6 , JavaFX is part of the Java SE, it is officially replacing Swing as Oracle’s UI library for Java, and it runs on (any) desktop, mobile, and within the browser (applet). Java SE 7 includes version JavaFX 2.2, Java SE 8 includes JavaFX8, i.e. the version we will use here.

In this blog, I would like to demonstrate how to create a simple stock ticker, written in JavaFX. Data will be fetched by calling a REST service from http://dev.markitondemand.com/#stockquote.
The url for the REST service returning the stockprice :

http://dev.markitondemand.com/Api/v2/Quote?symbol=GE

Where ‘GE’ is the symbol of the company.

Let’s start with some Eclipse setup first.

  1. install the e(fx)clipse plugin from following update site : http://download.eclipse.org/efxclipse/updates-released/1.0.0/site
  2. install the Scene Builder that will be used to design the screen. The Scene Builder is a piece of software that will help you create *.FXML files. These are plain xml files that contain the layout of your screen.
    http://www.oracle.com/technetwork/java/javase/downloads/sb2download-2177776.html is the one I used
    but newer versions can be downloaded from http://gluonhq.com/products/downloads/
  3. Install a JDK SE 8

So now we are ready to go. Open Eclipse and select ‘File’ -> ‘New’ -> ‘JavaFX Project’

selectproject

Enter a project name: StockTicker, set the JRE to a Java 8 install, and click finish.

createproject

A JavaFX project is created with a Main.java class. Right click the project , select Run As , Java Application, and you will see an empty window popping up. This shows that all components were correctly installed.

Our application contains a screen with a combo box, where we can select a company. After selection it will be added to a list view, where we can see its stock price update every 3 seconds. (If there is any trading activity of course : for more detail see http://www.batstrading.com/support/hours/ )

The Layout

In JavaFX we can create our UI in plain Java code or using .FXML files. We’ll use the latter here, as it creates a clean separation between the view and the model.

Right click the project -> New -> Other -> Package. Then enter the popup as shown below and click finish :

packageproject

Then right click the package -> New -> Other -> New FXML Document

fxmlproject

Click Next, enter ‘MainUI’ in the name of the fxml file.
Leave the Root Element as BorderPane. This is a layout with 5 areas : top,bottom, left and right. Click finish.

fxmlfileproject

A MainUI.fxml file is created. Replace the content by the following :

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane prefHeight="500.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <top>
      <Label text="Stock Ticker BATS Exchange" textAlignment="CENTER" BorderPane.alignment="CENTER">
         <font>
            <Font name="Arial" size="33.0" />
         </font>
      </Label>
   </top>
   <center>
      <VBox BorderPane.alignment="CENTER">
         <children>
            <ComboBox fx:id="cbQuote" prefHeight="20.0" prefWidth="350.0" promptText="Select a company">
               <VBox.margin>
                  <Insets bottom="20.0" left="75.0" top="20.0" />
               </VBox.margin></ComboBox>
            <TableView fx:id="listQuote" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
              <columns>
                <TableColumn fx:id="symbolCol" prefWidth="75.0" text="Symbol" />
                <TableColumn fx:id="companyCol" prefWidth="241.0" text="Company" />
                <TableColumn fx:id="lastpriceCol" prefWidth="153.0" text="Last Price" />
              </columns>
            </TableView>
         </children>
      </VBox>
   </center>
</BorderPane>

This XML already contains some links to code we will add later in the MainController.java class.
Save the .fxml file, right click the file and select ‘Open with Scene Builder’
The Scene Builder will start up and display the following screen :

scene1

Important here, is the Hierarchy block at the bottom left of the screen. It shows the structure of the layouts and components on the screen. We will use a BorderPane as the root layout, where a Label is added in the top area to use as a title. In the center area of the border pane, a VBox is added, containing a Combo Box (for selecting the quotes) and a TableView to view the quotes.

The Application

Now that we got the layout in place, we’ll start coding.
First of all, you can remove the generate package ‘application’ with its contents. It was generated by default by Eclipse, but we won’t be using it anymore.
Next step : create a new java class in the eu.iadvise.stockticker package, and call it MainApp.java. Use the following code :

public class MainApp extends Application {

	private Stage primaryStage;
    private BorderPane rootLayout;

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("BATS Ticker Application");
        FXMLLoader loader = null;
        try {
            // Load the root layout from the fxml file
            loader = new FXMLLoader(MainApp.class.getResource("MainUI.fxml"));
            rootLayout = (BorderPane) loader.load();
        } catch (Exception e) {
            // Exception gets thrown if the fxml file could not be loaded
        	System.out.println("FXML NOT LOADED !!!!!");
            e.printStackTrace();
        }
        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

	public static void main(String[] args) {
		launch(args);
	}
}

This is our primary class, where, first we set the title of the application window, then, we load the fxml that is used as layout, and then, we launch our application. By now our package explorer should look like this :

packagelayout

When you right click ‘StockTicker’ -> Run As -> Java Application, the application should be launched and will look like this :

firstscreen

 

The code for the REST call

Before we continue with the JavaFX components, we will create the necessary classes to execute the REST call, that picks up the stock quotes.

First, we create a Company class that will be used to populate the combo box.

public class Company {

	private String symbol;
	private String name;

	public Company(String symbol, String name) {
		super();
		this.symbol = symbol;
		this.name = name;
	}
	public String getSymbol() {
		return symbol;
	}
	public String getName() {
		return name;
	}

	// This method returns the value that is shown in the combobox.
	public String toString() {
		return this.name;
	}

	public static List<Company> getListCompanies() {
		List<Company> list = new ArrayList<Company>();
		list.add(new Company("SIRI","SIRIUS XM HLDGS INC COM"));
		list.add(new Company("ABX","BARRICK GOLD CORP COM"));
		list.add(new Company("GE","GENERAL ELECTRIC CO COM"));
		list.add(new Company("TLM","TALISMAN ENERGY INC COM"));
		list.add(new Company("AAPL","APPLE INC COM"));
		list.add(new Company("SPLS","STAPLES INC COM"));
		list.add(new Company("MSFT","MICROSOFT CORP COM"));
		list.add(new Company("PFE","PFIZER INC COM"));
		list.add(new Company("ORCL","ORACLE CORP."));
		list.add(new Company("BAC","BANK AMER CORP COM"));
		list.add(new Company("XOM","EXXON MOBIL CORP COM"));
		list.add(new Company("AA","ALCOA INC COM"));
		list.add(new Company("KO","COCA COLA CO COM"));
		list.add(new Company("C","CITIGROUP INC COM NEW"));
		return list;
	}
}

The getStockQuote method will execute the REST call to fetch the stock prices. Therefore we added the jersey-bundle-1.18.jar that contains all the necessary JAX-RS class to execute the call. Get this jar from : http://repo1.maven.org/maven2/com/sun/jersey/jersey-bundle/1.18/jersey-bundle-1.18.jar and add it to the project’s build path.

To get the result from the REST call we create the StockQuote class. This is basically just a value object. :

@XmlRootElement(name="StockQuote")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class StockQuote {

	private String name; //		Name of the company
	private String symbol; //		The company's ticker symbol
	private double lastPrice;//		The last price of the company's stock

	public String getSymbol() {
		return this.symbol;
	}

	public String getName() {
		return this.name;
	}

	public double getLastPrice() {
		return this.lastPrice;
	}

	@XmlElement(name="Name")
	public void setName(String name) {
		this.name = name;
	}

	@XmlElement(name="Symbol")
	public void setSymbol(String symbol) {
		this.symbol = symbol;
	}

	@XmlElement(name="LastPrice")
	public void setLastPrice(double lastPrice) {
		this.lastPrice = lastPrice;
	}

	@Override
	public String toString() {
		return "StockQuote [name=" + name + ", symbol=" + symbol
				+ ", lastPrice=" + lastPrice + "]";
	}

}

Finally, we need to add the stock quote class that will be used in the observable list. :

public class StockQuoteOL {

	private StringProperty symbol; //	Name of the company
	private StringProperty name; //	Name of the company
	private DoubleProperty lastPrice;//	The last price of the company's stock

	public StockQuoteOL(String symbol, String name, Double lastPrice) {
		super();
		this.symbol = new SimpleStringProperty(symbol);
		this.name = new SimpleStringProperty(name);
		this.lastPrice = new SimpleDoubleProperty(lastPrice);
	}

	public StringProperty getSymbol() {
		return symbol;
	}

	public void setSymbol(StringProperty symbol) {
		this.symbol = symbol;
	}

	public StringProperty getName() {
		return name;
	}

	public void setName(StringProperty name) {
		this.name = name;
	}

	public DoubleProperty getLastPrice() {
		return lastPrice;
	}

	public void setLastPrice(DoubleProperty lastPrice) {
		this.lastPrice = lastPrice;
	}

}

The StringProperty and DoubleProperty var’s will cause the components to update if the values of these variables are updated.

The JavaFX code

For each fxml in JavaFX, we create a controller class that contains the code handling all UI actions. So we create a MainController.java class with the following content :

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.util.Duration;

import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;

public class MainController {

    @FXML
    private ComboBox<Company> cbQuote;

    @FXML
    private TableView<StockQuoteOL> listQuote;
    private ObservableList<StockQuoteOL> listQuoteObservable = FXCollections.observableArrayList();
    @FXML
    private TableColumn<StockQuoteOL, String> symbolCol;
    @FXML
    private TableColumn<StockQuoteOL, String> companyCol;
    @FXML
    private TableColumn<StockQuoteOL, Number> lastpriceCol;    

    private ScheduledService<ObservableList<StockQuoteOL>> service;
    /**
     * Initializes the controller class. This method is automatically called
     * after the fxml file has been loaded.
     */
    @FXML
    public void initialize () {
        // fill up combobox with a list of companies
    	ObservableList<Company> listCompaniesObservable = FXCollections.observableArrayList();
    	listCompaniesObservable.addAll(Company.getListCompanies());
    	cbQuote.setItems(listCompaniesObservable);
        // add a change listener on the combobox
    	cbQuote.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Company>() {
	    	@Override
			public void changed(ObservableValue<? extends Company> observable,
					Company oldValue, Company newValue) {
	    			StockQuote stockQuote = getStockQuote(newValue.getSymbol());
	    			listQuoteObservable.add(new StockQuoteOL(stockQuote.getSymbol(),
	    					stockQuote.getName(),
	    					stockQuote.getLastPrice()) );
				}
	    	});
        // configure the listView with the stock quotes
    	listQuote.setItems(listQuoteObservable);
    	symbolCol.setCellValueFactory(cellData -> cellData.getValue().getSymbol());
    	companyCol.setCellValueFactory(cellData -> cellData.getValue().getName());
    	lastpriceCol.setCellValueFactory(cellData -> cellData.getValue().getLastPrice());
        // define the service to fetch the stock quotes
    	service = new PollingService(listQuoteObservable);
	    service.maximumFailureCountProperty().set(5);
	    service.setPeriod(Duration.seconds(3));
	    service.setOnFailed(new EventHandler<WorkerStateEvent>() {
	    	@Override
	    	public void handle(WorkerStateEvent event) {
	    		event.getSource().getException().printStackTrace();
	    		System.out.println(" Error in call : "+event.getSource().getException().getMessage());
	    	}
	    });
            // start the service that will run every 3 seconds
	    service.start();

    }

    class PollingService extends ScheduledService<ObservableList<StockQuoteOL>> {
    	private ObservableList<StockQuoteOL> listStockQuotes;
    	public PollingService(ObservableList<StockQuoteOL> listStockQuotes) {
    		this.listStockQuotes=listStockQuotes;
    	}
    	@Override
    	protected Task<ObservableList<StockQuoteOL>> createTask() {
    		return new PollingTask(listStockQuotes);
    	}
    }

    public class PollingTask extends Task<ObservableList<StockQuoteOL>> {
    	private ObservableList<StockQuoteOL> listStocks;
    		public PollingTask(ObservableList<StockQuoteOL> listStocks) {
    			this.listStocks = listStocks;
    		}
            @Override public ObservableList<StockQuoteOL> call() throws InterruptedException {
            	for (StockQuoteOL quote : listStocks) {
            		quote.getLastPrice().set(getStockQuote(quote.getSymbol().get()).getLastPrice());
            	}
            	return listStocks;
            }
    }

    public static StockQuote getStockQuote(String symbol) {
        Client c = Client.create();
        WebResource r = c.resource("http://dev.markitondemand.com/Api/v2/Quote?symbol="+symbol);
        ClientResponse response = r.accept( MediaType.APPLICATION_XML_TYPE).get(ClientResponse.class);
		StockQuote stockQuote =  response.getEntity(new GenericType<StockQuote>() {});
		System.out.println("Result REST call:"+stockQuote);
		return stockQuote;
    }   

}

This controller class contains the code for our MainUI.fxml layout.

To add this controller, open the MainUI.fxml in the scene builder, open the Controller section in the Document section, and select this class from the dropdown. (the eclipse plugin adds all possible controllers to this list)

controller

 

Remark : after updating and saving the .fxml file using the scene builder, make sure you refresh (F5) the file in Eclipse, otherwise the changes will not be picked up.

The member variables of the controller class, annotated with @FXML, refer to components in the .fxml file, defined with ‘fx:id’. Eg. : open the fxml in scene builder and select the combobox. in the Code section, you see the name of the member in the fx:id : cbQuote.

fxmlannot

Now we have our layout and the components, and the bindings between these components and the member variables in the controller class in place. The next step is to add functionality to the components.

In the initialize() method is executed on startup, and contains code for :

  • fill the combobox with a company list
  • add change listener on the combo box and add company
  • configuration of the list view for the stock quotes
  • definition of the service to fetch the stock quotes
  • Connect observable lists to our listview :
    cbQuote.setItems(listCompaniesObservable);
    listQuote.setItems(listQuoteObservable);
    Any changes (adding or updating of objects) in the observable list will now immediatly result in an update in the component.

As JavaFX runs in 1 thread, we will have to execute the REST service call to fetch the stock prices in a seperate thread, otherwise, the main UI would freeze during the call.

JavaFX has a few classes in the javafx.concurrent.* package that can be used to tackle this problem.

We wrote an extension on the ‘ScheduledService’ class : PollingService.java. This class executes a Task with any given time between the calls. Our Task (PollingTask.java) will fetch new prices for every company that is currently present in the listview. The service as a few methods for configuration purposes :

  • service.maximumFailureCountProperty().set(5) : After 5 failed calls, the service will stop
  • service.setPeriod(Duration.seconds(3)) : The service will be executed every 3 seconds.
  • service.setOnFailed : Callback method if the service fails. (There are more methods available like onSucceed,…)

The service.start() will eventually start the service.

Running the project

Right click the project an select Run as… Java Application.

BATS_Ticker_Application

Remember, if there is no trading at this moment, the prices will not change of course…

 

5 Minute JavaScript #8 Framework Design

In the last blogpost we talked about closures and how they provide a great way to hide variables and functions from the outside world. We can combine our knowledge about namespaces and closures to create a simple framework.

In JavaScript, frameworks aren’t just for external libraries. It’s good and common practice to define a JavaScript framework for your own application. This framework handles: namespaces, conflicts, modules, etc.. This framework is used for giving structure to your application, making it accessible, extendable, structured and readable.

In previous posts we talked about namespaces. These objects are fine for grouping functionality, but they don’t allow you to have shared variables for a certain package. When you add a closure that returns the framework object, you have a scope in which you can define package-specific variables and functions.

var Framework = function () {
	var privateVar = 'private';
	var publicVar = 'public';
    // you can declare functions inside functions!
	var privateFun = function () {}
	return {
		publicVar: 'public',
		publicVar: publicVar,
		getPublicVar: function () { return publicVar; },
		publicFun: function () {}
	};
}();

Note that the Framework function is executed immediately, resulting in an object that is stored in the Framework variable. However, the function allows you to define scoped variables and functions that are not accessible from outside the function.

This template provides you with an easy and elegant way to encapsulate code while still being able to export functions and properties.