SLogo Team Meeting
This exercise asks you to start the process of changing your thinking from simply programming to designing APIs. An Application Programming Interface, API, is simply all the public
classes and their public
methods. However, thinking about the public methods together as an interface to your program has the power to change how you perceive those methods from just something necessary to make the program functional to providing a service to other programmers (even those on your own team!). An API, then, essentially becomes a contract with developers, now clients, that they can rely on to be stable (even if the underlying implementation changes) and encourages them to extend the service's functionality.
Submitting your Work
At the end of lab, push
your team's markdown files to the doc
folder of your provided, shared, slogo_teamNN
repository to submit your notes about your teams' discussions.
Make sure the text of your final commit message is of the form "lab_slogo_design - NetIDs".
Lab Workflow
In your SLogo teams, complete the following activities today:
- Introduce yourselves by sharing:
- your background and how you are doing in general this semester
- your motivation/interest in this course
- your knowledge/interest in other programming languages (especially Logo, Alice, Scratch, Lisp, or something similar) and APIs
- areas of the project you interested/concerned about
- Discuss each person's team experiences and expectations:
- share good and bad past team experiences and what you learned from them
- share preferences and styles regarding expectations, communication, and debating/conflict
- go over the Team Contract (which you will submit individually)
- choose a time for the next team meeting
- Practice thinking about the design if APIs
- examine Java's Collections API from a design perspective (instead of as a user) to see how it is documented and motivated in the file COLLECTION_API.md
- review someone's Cell Society project to understand its existing APIs and to help you create more deliberate ones in the file SIMULATION_API.md
- Share your ideas for the project and start planning your project
clone
the shared slogo_teamNN
repository to your machine and Open
the project within IntelliJ
- for each API, create a "one page" description of its design goals, contract obligations, and services provided in the file SLOGO_APIs.md
- use CRC cards to refine your design, focusing more on the interactions between classes than their implementation
- use Use Cases to verify the completeness and flexibility of your design, by writing "example code", a sequence of method calls from those on your CRC cards
For shared Markdown editing, you can work
Understanding an API
Although the concept is inherently subjective, most developers seem to agree on the main desirable characteristics of an API:
- Easy to learn
- Encourages extension
- Leads to readable code
- Hard to misuse
Each person should examine one of the following documents about Java's Collections API and discuss with the rest of the team how well it follows the above characteristics:
Of course, you should bring your own experience using collections by comparing them to the API's design goals. If there is something you like or dislike or something your learned about design during the discussion, make sure to back it up with a specific example.
Some things for you to consider:
- In your experience using these collections, are they hard or easy to use?
- In your experience using these collections, do you feel mistakes are easy to avoid?
- What methods are common to all collections (and why are
Map
s excluded)? What methods are common to all Deque
s?
- How many interfaces do specific concrete collection classes implement (such as
LinkedList
)? What is the purpose of each interface?
- How many different implementations are there for a specific collection class (such as
Set
)? Do you think the number justifies it being an interface or not?
- How many superclasses do specific concrete collection classes have (such as
PriorityQueue
)? What do you think is the purpose of each inheritance "level"?
- Why does it make sense to have the utility classes (such as
Collections
) instead of adding that functionality to specific collection types themselves (such as List
)?
- Are there any overlapping methods (ones that are in both a specific collection and a utility class)?
- If so, is there any guidance on which one you should use?
API Discovery
In many projects, APIs can serve two different goals based on the clients (other programmers): consumers that use the API and providers that implement/maintain the API:
- External API:
- typical goal: how to provide useful access to information that encapsulates the implementation details while encouraging extensions for as wide a variety of "unexpected" features as possible
- such as: between the frontend and backend (e.g., between programmers in the project's other sub-groups, which provide their own external APIs)
- such as: between the platform and developers for the platform (e.g., between iOS and app developers or between Facebook and add-ons or game developers)
- note: all of these methods will need to be
public
- vision:
- What services can you provide to encourage users to add their own new functionality?
- How do you plan to encapsulate users from implementation changes?
- What objects will be used for communication, making clear:
- how needed information will get where it is needed
- how to make the process as active as possible (not just giving out raw data)?
- what will be abstractions?
- what things will be immutable?
- what errors may be thrown?
- Internal API:
- typical goal: how to provide paths for extension through addition for expected new features while keeping the core implementation closed to modification
- such as: between the backend and its future maintenance programmers (e.g., between programmers within the same sub-group)
- such as: between the platform and developers that port that platform to new technologies (e.g., between Facebook and its mobile and web teams)
- note: while most of these methods may be
public
, many may be protected
or package friendly
- vision:
- How do you plan to provide paths for extension by adding new classes for new features you might reasonably expect to be added to the program?
- What subclasses or implementing classes will be used to extend your part to add new features, making it clear:
- what kind of additional code someone will be expected to write?
- how to make as many parts of the code as possible closed to modification?
- what errors may be thrown?
Examine one person's Cell Society project the perspective of APIs by categorizing each public
or protected
method in the Simulation part as:
- should not be part of the Simulation API (i.e., it should have been made
private
)
- should be part of the external API because it serves users/consumers (programmers working on the View or Configuration parts)
- should be part of the internal API because it serves providers/maintainers (programmers working within the Simulation part)
A simplified view of only the public
/protected
methods for each team is available here.
Now that you have a sense of the kind of service your project actually provides to programmers, think about the kind of service you wish it provided. In other words, spend this time designing the API instead of just having it happen. Write a simplified (i.e., less than "one page" each) description and goals of both the internal and external Simulation API. Note which classes are abstract
/interface
and which concrete and, for concrete classes that are part of the external API, justify why they do not need to represent an abstraction.
Then describe how to use your new external and internal APIs to do the following tasks:
- external: as a client of the backend, the frontend selects an existing simulation to display and then starts running that kind of simulation, updating its own grid visualization
- internal: a new developer joins the the backend team and adds a new possible kind of simulation that can then be selectable by the frontend
Your written explanation should include both English and Java descriptions of the task:
- English: how do you want programmers to think of the process of using the API to accomplish this task using metaphors or analogies (e.g., folder paradigm), or standard programming ideas (e.g., step by step or substitution via polymorphism) beyond simply restating the procedural steps
- Java: list the actual Java methods you expect to use from the API to accomplish this task with a comment about how they would be used (e.g., call, implement, or change)
SLogo APIs
Discuss high level design ideas and possible APIs for the SLogo project without worrying about the implementation details (a specific data structure, the parsing algorithm, or the exact layout and OpenJFX components needed). Also discuss any issues or concerns anyone has about the project's specifications or goals.
Consider the following questions:
- What behaviors (methods) should the Turtle have and what service should it provide?
- When does parsing need to take place and what does it need to start properly?
- What is the result of parsing (not the details of the algorithm) and who receives it?
- When are errors detected and how are they reported?
- What do different commands need to know, when do they know it, and how do they get it?
- What behaviors does the result of a command need to have to be used by the View?
- How is the View updated after a command has completed execution?
- What value would Controller(s) have in mediating between the Model and View?
Write a simplified description for each of the project APIs (i.e., no more than "one page" each) that incorporates your vision for each as well as the public
classes and methods. Note which classes you expect to be abstractions (e.g., abstract
or interface
) and which concrete. For the concrete classes, justify why they do not need to be an abstraction. A class's behavior is its public methods, including any parameters and a return value. These method signatures can be written as they would appear in Java code, but your focus should be on describing their purpose in the class, not their implementation. To summarize a class and its purpose, highlight only the most important methods in this first draft.
Ideally, without any coding or requiring any specific implementation, try to explore trade-offs between several designs and to determine the best one to explore in detail (creating simplified UML style pictures can be helpful here using Markdown).
Class-Responsibility-Collaborator Cards
Now that your team has thought about the problem generally, use CRC cards to refine your design and help you focus on interface instead of implementation issues. A CRC card help show the objects more conceptually and the logical relationship between objects more explicitly, making it is easier to understand, evaluate, and modify a design. Answering the following questions about each class helps see them as smart/anthropomorphic collaborators:
- What active behaviors is this class responsible for (rather than get/set methods)?
These are the public methods other objects can call on this one without knowing how it implements that behavior.
- What other classes are required to help this class fulfill those responsibilities?
These other classes will either be passed to this object's constructor or methods, returned from a method, or created by this object itself.
Here are some examples of completed CRC cards. In these examples, the actions are given in English, not as a Java method signature (name, parameters, and return type). Your version must be written as a Java signature to provide more details about the flow of the program.
Use Cases
The following scenarios are provided to help test the completeness of your design. By writing the steps needed to complete each case below you will be able to see how effectively your design handles these scenarios and others will be able to better understand how deeply you have considered the basic issues. It may help to role play or draw a diagram of how your classes collaborate to complete each case. For this exercise each step, try to include both the class used and the method used to accomplish the step.
- The user types 'fd 50' in the
command window, sees the turtle move in the display window leaving a
trail, and has the command added to the environment's history.
- The user types '50 fd' in the
command window and sees an error message that the command was not formatted correctly.
- The user types 'pu fd 50 pd fd 50' in the command window and sees the turtle move twice (once without a trail and once with a trail).
- The user changes the color of the environment's background.
Here are some examples of completed Use Cases. In these examples, the steps are given in English, not as a Java method calls. Your version should be written as a sequence of calls to only those Java methods on your CRC cards to provide more details about the flow of the program.
To make things more interesting, pair up with another team and try to do this part using their CRC cards!