Module: CryptIdent
- Extended by:
- Dry::Configurable
- Defined in:
- lib/crypt_ident/config.rb,
lib/crypt_ident/sign_in.rb,
lib/crypt_ident/sign_up.rb,
lib/crypt_ident/version.rb,
lib/crypt_ident/sign_out.rb,
lib/crypt_ident/reset_password.rb,
lib/crypt_ident/change_password.rb,
lib/crypt_ident/session_expired.rb,
lib/crypt_ident/generate_reset_token.rb,
lib/crypt_ident/update_session_expiry.rb
Overview
Include and interact with CryptIdent
to add authentication to a
Hanami controller action.
Note the emphasis on controller action; this module interacts with session data, which is quite theoretically possible in an Interactor but practically quite the PITA. YHBW.
Constant Summary collapse
- VERSION =
Version number for Gem. Uses Semantic Versioning.
'0.2.3'
Instance Method Summary collapse
-
#change_password(user_in, current_password, new_password) {|result| ... }
Change an Authenticated User's password.
-
#generate_reset_token(user_name, current_user: nil) {|result| ... }
Generate a Password Reset Token.
-
#reset_password(token, new_password, current_user: nil) {|result| ... }
Reset the password for the User associated with a Password Reset Token.
-
#session_expired?(session_data = {}) ⇒ Boolean
Determine whether the Session has Expired due to User inactivity.
-
#sign_in(user_in, password, current_user: nil) {|result| ... }
Attempt to Authenticate a User, passing in an Entity for that User (which must contain a
password_hash
attribute), and a Clear-Text Password. -
#sign_out(current_user:) {|result| ... }
Sign out a previously Authenticated User.
-
#sign_up(attribs, current_user:) {|result| ... }
Persist a new User to a Repository based on passed-in attributes, where the resulting Entity (on success) contains a
:password_hash
attribute containing the encrypted value of a random Clear-Text Password; anypassword
value withinattribs
is ignored. -
#update_session_expiry(session_data = {}) ⇒ Hash
Generate a Hash containing an updated Session Expiration timestamp, which can then be used for session management.
Instance Method Details
#change_password(user_in, current_password, new_password) {|result| ... }
This method returns an undefined value.
Change an Authenticated User's password.
To change an Authenticated User's password, an Entity for that User, the
current Clear-Text Password, and the new Clear-Text Password are required.
The method accepts an optional repo
parameter to specify a Repository
instance to which the updated User Entity should be persisted; if none is
specified (i.e., if the parameter has its default value of nil
), then the
UserRepository
specified in the Configuration is used.
The method requires a block, to which a result
indicating success or
failure is yielded. That block must in turn call both
result.success
and result.failure
to handle success and failure results,
respectively. On success, the block yielded to by result.success
is called
and passed a user:
parameter, which is identical to the user
parameter
passed in to #change_password
except that the :password_hash
attribute
has been updated to reflect the changed password. The updated value for the
encrypted password will also have been saved to the Repository.
On failure, the result.failure
call will yield a code:
parameter to its
block, which indicates the cause of failure as follows:
If the specified password did not match the passed-in user
Entity, then
the code:
for failure will be :bad_password
.
If the specified user
was other than a User Entity representing a
Registered User, then the code:
for failure will be :invalid_user
.
Note that no check for the Current User is done here; this method trusts the Controller Action Class that (possibly indirectly) invokes it to guard that contingency properly.
103 104 105 106 107 108 |
# File 'lib/crypt_ident/change_password.rb', line 103 def change_password(user_in, current_password, new_password) call_params = [current_password, new_password] ChangePassword.new(user: user_in).call(*call_params) do |result| yield result end end |
#generate_reset_token(user_name, current_user: nil) {|result| ... }
This method returns an undefined value.
Generate a Password Reset Token
Password Reset Tokens are useful for verifying that the person requesting a Password Reset for an existing User is sufficiently likely to be the person who Registered that User or, if not, that no compromise or other harm is done.
Typically, this is done by sending a link through email or other such medium
to the address previously associated with the User purportedly requesting
the Password Reset. CryptIdent
does not automate generation or sending
of the email message. What it does provide is a method to generate a new
Password Reset Token to be embedded into an HTML anchor link within an email
that you construct, and then another method (#reset_password
) to actually
change the password given a valid, correct token.
It also implements an expiry system, such that if the confirmation of the Password Reset request is not completed within a configurable time, that the token is no longer valid (and so cannot be later reused by unauthorised persons).
This method requires a block, to which a result
indicating success or
failure is yielded. That block must in turn call both
result.success
and result.failure
to handle success and failure results,
respectively. On success, the block yielded to by result.success
is called
and passed a user:
parameter, which is identical to the user
parameter
passed in to #generate_reset_token
except that the :token
and
:password_reset_expires_at
attributes have been updated to reflect the
token request. An updated record matching that :user
Entity will also have
been saved to the Repository.
On failure, the result.failure
call will yield three parameters: :code
,
:current_user
, and :name
, and will be set as follows:
If the :code
value is :user_logged_in
, that indicates that the
current_user
parameter to this method represented a Registered User. In
this event, the :current_user
value passed in to the result.failure
call
will be the same User Entity passed into the method, and the :name
value
will be :unassigned
.
If the :code
value is :user_not_found
, the named User was not found in
the Repository. The :current_user
parameter will be the Guest User Entity,
and the :name
parameter to the result.failure
block will be the
user_name
value passed into the method.
113 114 115 116 117 118 |
# File 'lib/crypt_ident/generate_reset_token.rb', line 113 def generate_reset_token(user_name, current_user: nil) other_params = { current_user: current_user } GenerateResetToken.new.call(user_name, other_params) do |result| yield result end end |
#reset_password(token, new_password, current_user: nil) {|result| ... }
This method returns an undefined value.
Reset the password for the User associated with a Password Reset Token.
After a Password Reset Token has been generated and sent to a User, that User would then exercise the Client system and perform a Password Reset.
Calling #reset_password
is different than calling #change_password
in
one vital respect: with #change_password
, the User involved must be
the Current User (as presumed by passing the appropriate User Entity in as
the current_user:
parameter), whereas #reset_password
must not be
called with any User other than the Guest User as the current_user:
parameter (and, again presumably, the Current User for the session). How can
we assure ourselves that the request is legitimate for a specific User? By
use of the Token generated by a previous call to #generate_reset_token
,
which is used in place of a User Name for this request.
Given a valid set of parameters, and given that the updated User is
successfully persisted, the method calls the required block with a
result
whose result.success
matcher is yielded a user:
parameter with
the updated User as its value.
NOTE: Each of the error returns documented below calls the required
block with a result
whose result.failure
matcher is yielded a code:
parameter as described, and a token:
parameter that has the same value
as the passed-in token
parameter.
If the passed-in token
parameter matches the token
field of a record in
the Repository and that Token is determined to have Expired, then the
code:
parameter mentioned earlier will have the value :expired_token
.
If the passed-in token
parameter does not match the token
field of any
record in the Repository, then the code:
parameter will have the value
:token_not_found
.
If the passed-in current_user:
parameter is a Registered User, then the
code:
parameter will have the value :invalid_current_user
.
In no event are session values, including the Current User, changed. After a successful Password Reset, the User must Authenticate as usual.
111 112 113 114 115 116 |
# File 'lib/crypt_ident/reset_password.rb', line 111 def reset_password(token, new_password, current_user: nil) other_params = { current_user: current_user } ResetPassword.new.call(token, new_password, other_params) do |result| yield result end end |
#session_expired?(session_data = {}) ⇒ Boolean
Determine whether the Session has Expired due to User inactivity.
This is one of two methods in CryptIdent
(the other being
#update_session_expiry?
) which does not follow
the result
/success/failure monad workflow. This is because
there is no success/failure division in the workflow. Calling the method
determines if the Current User session has Expired. If the passed-in
:current_user
is a Registered User, then this will return true
if the
current time is later than the passed-in :expires_at
value; for the
Guest User, it should always return false
. (Guest User sessions never
expire; after all, what would you change the session state to?).
The client code is responsible for applying these values to its own actual session data, as described by the sample session-management code shown in the README.
58 59 60 |
# File 'lib/crypt_ident/session_expired.rb', line 58 def session_expired?(session_data = {}) SessionExpired.new.call(session_data) end |
#sign_in(user_in, password, current_user: nil) {|result| ... }
This method returns an undefined value.
Attempt to Authenticate a User, passing in an Entity for that User (which
must contain a password_hash
attribute), and a Clear-Text Password.
It also passes in the Current User.
If the Current User is not a Registered User, then Authentication of the
specified User Entity against the specified Password is accomplished by
comparing the User Entity's password_hash
attribute to the passed-in
Clear-Text Password.
The method requires a block, to which a result
indicating success or
failure is yielded. That block must in turn call both
result.success
and result.failure
to handle success and failure results,
respectively. On success, the block yielded to by result.success
is called
and passed a user:
parameter, which is the Authenticated User (and is the
same Entity as the user
parameter passed in to #sign_in
).
On failure, the result.failure
call will yield a code:
parameter to its
block, which indicates the cause of failure as follows:
If the specified password did not match the passed-in user
Entity, then
the code:
for failure will be :invalid_password
.
If the specified user
was not a Registered User, then the code:
for
failure will be :user_is_guest
.
If the specified current_user
is neither the Guest User nor the user
passed in as a parameter to #sign_in
, then the code:
for failure will be
:illegal_current_user
.
On success, the Controller-level client code must set:
session[:expires_at]
to the expiration time for the session. This is ordinarily computed by adding the current time as returned byTime.now
to the:session_expiry
value in the current configuration.session[:current_user]
to tne returned Entity for the successfully Authenticated User. This is to eliminate possible repeated reads of the Repository.
On failure, the Controller-level client code should set:
session[:expires_at]
to some sufficiently-past time to always trigger#session_expired?
;Hanami::Utils::Kernel.Time(0)
does this quite well (returning midnight GMT on 1 January 1970, converted to local time).session[:current_user]
to eithernil
or the Guest User.
123 124 125 126 |
# File 'lib/crypt_ident/sign_in.rb', line 123 def sign_in(user_in, password, current_user: nil) params = { user: user_in, password: password, current_user: current_user } SignIn.new.call(params) { |result| yield result } end |
#sign_out(current_user:) {|result| ... }
This method returns an undefined value.
Sign out a previously Authenticated User.
The method requires a block, to which a result
indicating success or
failure is yielded. (Presently, any call to #sign_out
results in success.)
That block must in turn call both result.success
and
result.failure
(even though no failure is implemented) to handle success
and failure results, respectively. On success, the block yielded to by
result.success
is called without parameters.
74 75 76 |
# File 'lib/crypt_ident/sign_out.rb', line 74 def sign_out(current_user:) SignOut.new.call(current_user: current_user) { |result| yield result } end |
#sign_up(attribs, current_user:) {|result| ... }
This method returns an undefined value.
Persist a new User to a Repository based on passed-in attributes, where the
resulting Entity (on success) contains a :password_hash
attribute
containing the encrypted value of a random Clear-Text Password; any
password
value within attribs
is ignored.
The method requires a block, to which a result
indicating success or
failure is yielded. That block must in turn call both
result.success
and result.failure
to handle success and failure results,
respectively. On success, the block yielded to by result.success
is called
and passed a user:
parameter, which is the newly-created User Entity.
If the call fails, the result.success
block is yielded to, and passed a
code:
parameter, which will contain one of the following symbols:
:current_user_exists
indicates that the method was called with a Registered User as thecurrent_user
parameter.:user_already_created
indicates that the specifiedname
attribute matches a record that already exists in the underlying Repository.:user_creation_failed
indicates that the Repository was unable to create the new User for some other reason, such as an internal error.
NOTE that the incoming params
are expected to have been whitelisted at
the Controller Action Class level.
87 88 89 90 91 |
# File 'lib/crypt_ident/sign_up.rb', line 87 def sign_up(attribs, current_user:) SignUp.new.call(attribs, current_user: current_user) do |result| yield result end end |
#update_session_expiry(session_data = {}) ⇒ Hash
Generate a Hash containing an updated Session Expiration timestamp, which can then be used for session management.
This is one of two methods in CryptIdent
(the other being
#session_expired?
) which does not follow the
result
/success/failure monad workflow. This is because
there is no success/failure division in the workflow. Calling the method
only makes sense if there is a Registered User as the Current User, but all
this method does is build a Hash with :current_user
and :expires_at
entries. The returned :current_user
is the passed-in :current_user
if a
Registered User, or the Guest User if not. The returned :updated_at
value,
for a Registered User, is the configured Session Expiry added to the current
time, and for the Guest User, a time far enough in the future that any call
to #session_expired?
will be highly unlikely to ever return true
.
The client code is responsible for applying these values to its own actual session data, as described by the sample session-management code shown in the README.
74 75 76 |
# File 'lib/crypt_ident/update_session_expiry.rb', line 74 def update_session_expiry(session_data = {}) UpdateSessionExpiry.new.call(session_data) end |


{% extends 'base.html' %} {% block top_content %} {% endblock %} {% block main_content %}
{# I18N: Shown after the student has submitted an assessment. #}
{{ gettext('Thank you for taking the %(assessment_name)s. Your score for this assessment
is %(score)s%%.' % {'assessment_name': assessment_name|lower, 'score': score})|safe }}
{% if is_last_assessment %}
You need to earn 70% or higher, and earn the previous 3 badges, to qualify for the final
badge.
{% else %}
You need to earn an 80% or higher in order to be awarded the Expertise badge for
this section of the course.
{% endif %}
{% if can_take_again %}
You can take the test again and change your answers if you think you can improve your score. Please
USE THIS LINK instead of hitting the back button; the web site will
remember your previous answers.
{% endif %}
This was the last exam of the course! Assessment Expert badges will be issued a couple of days after the exam closes. To claim this badge, if you've earned it, we will ask you to fill out a short (5-10 minute) survey about the course. More details will be available very soon, and will be sent to you by announcement.
{% endif %}


Connectivity
Table of Contents:
ActivityStarter
A component that can launch an activity using the StartActivity method.
Activities that can be launched include:
- Starting another App Inventor for Android app. To do so, first find out the class of the other
application by downloading the source code and using a file explorer or unzip utility to find
a file named “youngandroidproject/project.properties”. The first line of the file will start
with “main=” and be followed by the class name; for example,
main=com.gmail.Bitdiddle.Ben.HelloPurr.Screen1
. (The first components indicate that it was created by<EMAIL_ADDRESS>To make yourActivityStarter
launch this application, set the following properties:ActivityPackage
to the class name, dropping the last component (for example,com.gmail.Bitdiddle.Ben.HelloPurr
)ActivityClass
to the entire class name (for example,com.gmail.Bitdiddle.Ben.HelloPurr.Screen1
)
- Starting the camera application by setting the following properties:
Action
:android.intent.action.MAIN
ActivityPackage
:com.android.camera
ActivityClass
:com.android.camera.Camera
- Performing web search. Assuming the term you want to search for is “vampire” (feel free to substitute your own choice), set the properties to:
Action
:android.intent.action.WEB_SEARCH
ExtraKey
:query
ExtraValue
:vampire
ActivityPackage
:com.google.android.providers.enhancedgooglesearch
ActivityClass
:com.google.android.providers.enhancedgooglesearch.Launcher
- Opening a browser to a specified web page. Assuming the page you want to go to is “www.facebook.com” (feel free to substitute your own choice), set the properties to:
Action
:android.intent.action.VIEW
DataUri
:http://www.facebook.com
Properties
- Action
- Specifies the action that will be used to start the activity.
- ActivityClass
- Specifies the class part of the specific component that will be started.
- ActivityPackage
- Specifies the package part of the specific component that will be started.
- DataType
- Specifies the MIME type to pass to the activity.
- DataUri
- Specifies the data URI that will be used to start the activity.
- ExtraKey
- Specifies the extra key that will be passed to the activity. Obsolete. Should use Extras instead
- ExtraValue
- Specifies the extra value that will be passed to the activity. Obsolete. Should use Extras instead
- Extras
- Returns the list of key-value pairs that will be passed as extra data to the activity.
- Result
- Returns the result from the activity.
- ResultName
- Specifies the name that will be used to retrieve a result from the activity.
- ResultType
- Returns the MIME type from the activity.
- ResultUri
- Returns the URI from the activity.
Events
- ActivityCanceled()
- Event raised if this `ActivityStarter returns because the activity was canceled.
- AfterActivity(result)
- Event raised after this
ActivityStarter
returns.
Methods
- ResolveActivity()
- Returns the name of the activity that corresponds to this
ActivityStarter
, or an empty string if no corresponding activity can be found. - StartActivity()
- Start the activity corresponding to this
ActivityStarter
.
BluetoothClient
Use BluetoothClient
to connect your device to other devices using Bluetooth. This component
uses the Serial Port Profile (SPP) for communication. If you are interested in using Bluetooth
low energy, please see the
BluetoothLE extension.
Properties
- AddressesAndNames
- Returns the list of paired Bluetooth devices. Each element of the returned list is a String consisting of the device’s address, a space, and the device’s name.
- Available
- Returns
true
if Bluetooth is available on the device,false
otherwise. - CharacterEncoding
- Returns the character encoding to use when sending and receiving text.
- DelimiterByte
- Returns the delimiter byte to use when passing a negative number for the numberOfBytes parameter when calling ReceiveText, ReceiveSignedBytes, or ReceiveUnsignedBytes.
- DisconnectOnError
- Specifies whether BluetoothClient/BluetoothServer should be disconnected automatically when an error occurs.
- Enabled
- Returns
true
if Bluetooth is enabled,false
otherwise. - HighByteFirst
- Specifies whether numbers are sent and received with the most significant byte first.
- IsConnected
- Returns
frue
if a connection to a Bluetooth device has been made. - PollingRate
- Returns the configured polling rate value of the Bluetooth Client.
- Secure
- Specifies whether a secure connection should be used.
Events
None
Methods
- BytesAvailableToReceive()
- Returns number of bytes available from the input stream.
- Connect(address)
- Connect to a Bluetooth device with the given address.
- ConnectWithUUID(address,uuid)
- Connect to a Bluetooth device with the given address and a specific UUID.
- Disconnect()
- Disconnects from the connected Bluetooth device.
- IsDevicePaired(address)
- Checks whether the Bluetooth device with the given address is paired.
- ReceiveSigned1ByteNumber()
- Reads a signed 1-byte number.
- ReceiveSigned2ByteNumber()
- Reads a signed 2-byte number.
- ReceiveSigned4ByteNumber()
- Reads a signed 4-byte number.
- ReceiveSignedBytes(numberOfBytes)
- Reads a number of signed bytes from the input stream and returns them as
a List.
If numberOfBytes is negative, this method reads until a delimiter byte value is read. The delimiter byte value is included in the returned list.
- ReceiveText(numberOfBytes)
- Reads a number of bytes from the input stream and converts them to text.
If numberOfBytes is negative, read until a delimiter byte value is read.
- ReceiveUnsigned1ByteNumber()
- Reads an unsigned 1-byte number.
- ReceiveUnsigned2ByteNumber()
- Reads an unsigned 2-byte number.
- ReceiveUnsigned4ByteNumber()
- Reads an unsigned 4-byte number.
- ReceiveUnsignedBytes(numberOfBytes)
- Reads a number of unsigned bytes from the input stream and returns them as
a List.
If numberOfBytes is negative, this method reads until a delimiter byte value is read. The delimiter byte value is included in the returned list.
- Send1ByteNumber(number)
- Decodes the given number String to an integer and writes it as one byte
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in one byte, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- Send2ByteNumber(number)
- Decodes the given number String to an integer and writes it as two bytes
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in two bytes, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- Send4ByteNumber(number)
- Decodes the given number String to an integer and writes it as four bytes
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in four bytes, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- SendBytes(list)
- Takes each element from the given list, converts it to a String, decodes
the String to an integer, and writes it as one byte to the output stream.
If an element could not be decoded to an integer, or the integer would not fit in one byte, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- SendText(text)
- Converts the given text to bytes and writes them to the output stream.
BluetoothServer
Use the BluetoothServer
component to turn your device into a server that receive connections
from other apps that use the BluetoothClient
component.
Properties
- Available
- Returns
true
if Bluetooth is available on the device,false
otherwise. - CharacterEncoding
- Returns the character encoding to use when sending and receiving text.
- DelimiterByte
- Returns the delimiter byte to use when passing a negative number for the numberOfBytes parameter when calling ReceiveText, ReceiveSignedBytes, or ReceiveUnsignedBytes.
- Enabled
- Returns
true
if Bluetooth is enabled,false
otherwise. - HighByteFirst
- Specifies whether numbers are sent and received with the most significant byte first.
- IsAccepting
- Returns true if this BluetoothServer component is accepting an incoming connection.
- IsConnected
- Returns
frue
if a connection to a Bluetooth device has been made. - Secure
- Specifies whether a secure connection should be used.
Events
- ConnectionAccepted()
- Indicates that a bluetooth connection has been accepted.
Methods
- AcceptConnection(serviceName)
- Accept an incoming connection with the Serial Port Profile (SPP).
- AcceptConnectionWithUUID(serviceName,uuid)
- Accept an incoming connection with a specific UUID.
- BytesAvailableToReceive()
- Returns number of bytes available from the input stream.
- Disconnect()
- Disconnects from the connected Bluetooth device.
- ReceiveSigned1ByteNumber()
- Reads a signed 1-byte number.
- ReceiveSigned2ByteNumber()
- Reads a signed 2-byte number.
- ReceiveSigned4ByteNumber()
- Reads a signed 4-byte number.
- ReceiveSignedBytes(numberOfBytes)
- Reads a number of signed bytes from the input stream and returns them as
a List.
If numberOfBytes is negative, this method reads until a delimiter byte value is read. The delimiter byte value is included in the returned list.
- ReceiveText(numberOfBytes)
- Reads a number of bytes from the input stream and converts them to text.
If numberOfBytes is negative, read until a delimiter byte value is read.
- ReceiveUnsigned1ByteNumber()
- Reads an unsigned 1-byte number.
- ReceiveUnsigned2ByteNumber()
- Reads an unsigned 2-byte number.
- ReceiveUnsigned4ByteNumber()
- Reads an unsigned 4-byte number.
- ReceiveUnsignedBytes(numberOfBytes)
- Reads a number of unsigned bytes from the input stream and returns them as
a List.
If numberOfBytes is negative, this method reads until a delimiter byte value is read. The delimiter byte value is included in the returned list.
- Send1ByteNumber(number)
- Decodes the given number String to an integer and writes it as one byte
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in one byte, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- Send2ByteNumber(number)
- Decodes the given number String to an integer and writes it as two bytes
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in two bytes, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- Send4ByteNumber(number)
- Decodes the given number String to an integer and writes it as four bytes
to the output stream.
If the number could not be decoded to an integer, or the integer would not fit in four bytes, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- SendBytes(list)
- Takes each element from the given list, converts it to a String, decodes
the String to an integer, and writes it as one byte to the output stream.
If an element could not be decoded to an integer, or the integer would not fit in one byte, then the Form’s ErrorOccurred event is triggered and this method returns without writing any bytes to the output stream.
- SendText(text)
- Converts the given text to bytes and writes them to the output stream.
- StopAccepting()
- Stop accepting an incoming connection.
Serial
Component for Serial
Properties
- BaudRate
- Returns the current baud rate
- BufferSize
- Returns the buffer size in bytes
- IsInitialized
- Returns true when the Serial has been initialized.
- IsOpen
- Returns true when the Serial connection is open.
Events
None
Methods
- CloseSerial()
- Closes serial connection. Returns true when closed.
- InitializeSerial()
- Initializes serial connection.
- OpenSerial()
- Opens serial connection. Returns true when opened.
- PrintSerial(data)
- Writes given data to serial, and appends a new line at the end.
- ReadSerial()
- Reads data from serial.
- WriteSerial(data)
- Writes given data to serial.
Web
Non-visible component that provides functions for HTTP GET, POST, PUT, and DELETE requests.
Properties
- AllowCookies
- Specifies whether cookies should be allowed
- RequestHeaders
- Sets the request headers.
- ResponseFileName
- Specifies the name of the file where the response should be saved. If SaveResponse is true and ResponseFileName is empty, then a new file name will be generated.
- SaveResponse
- Specifies whether the response should be saved in a file.
- Timeout
- Returns the number of milliseconds that each request will wait for a response before they time out. If set to 0, then the request will wait for a response indefinitely.
- Url
- Specifies the URL.
Events
- GotFile(url,responseCode,responseType,fileName)
- Event indicating that a request has finished.
- GotText(url,responseCode,responseType,responseContent)
- Event indicating that a request has finished.
- TimedOut(url)
- Event indicating that a request has timed out.
Methods
- BuildRequestData(list)
- Converts a list of two-element sublists, representing name and value pairs, to a string formatted as application/x-www-form-urlencoded media type, suitable to pass to PostText.
- ClearCookies()
- Clears all cookies for this Web component.
- Delete()
- Performs an HTTP DELETE request using the Url property and retrieves the
response.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- Get()
- Performs an HTTP GET request using the Url property and retrieves the
response.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- HtmlTextDecode(htmlText)
- Decodes the given HTML text value.
HTML Character Entities such as
&
,<
,>
,'
, and"
are changed to&
,<
,>
,'
, and"
. Entities such as&#xhhhh;
, and&#nnnn;
are changed to the appropriate characters. - JsonObjectEncode(jsonObject)
- Returns the value of a built-in type (i.e., boolean, number, text, list, dictionary) in its JavaScript Object Notation representation. If the value cannot be represented as JSON, the Screen’s ErrorOccurred event will be run, if any, and the Web component will return the empty string.
- JsonTextDecode(jsonText)
- Decodes the given JSON encoded value to produce a corresponding AppInventor value.
A JSON list
[x, y, z]
decodes to a list(x y z)
, A JSON object with key A and value B, (denoted as{A:B}
) decodes to a list((A B))
, that is, a list containing the two-element list(A B)
.Use the method JsonTextDecodeWithDictionaries if you would prefer to get back dictionary objects rather than lists-of-lists in the result.
- JsonTextDecodeWithDictionaries(jsonText)
- Decodes the given JSON encoded value to produce a corresponding App Inventor value. A JSON list [x, y, z] decodes to a list (x y z). A JSON Object with name A and value B, denoted as {a: b} decodes to a dictionary with the key a and value b.
- PatchFile(path)
- Performs an HTTP PATCH request using the Url property and data from the specified file.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PatchText(text)
- Performs an HTTP PATCH request using the Url property and the specified text.
The characters of the text are encoded using UTF-8 encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The responseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PatchTextWithEncoding(text,encoding)
- Performs an HTTP PATCH request using the Url property and the specified text.
The characters of the text are encoded using the given encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PostFile(path)
- Performs an HTTP POST request using the Url property and data from the specified file.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PostText(text)
- Performs an HTTP POST request using the Url property and the specified text.
The characters of the text are encoded using UTF-8 encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The responseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PostTextWithEncoding(text,encoding)
- Performs an HTTP POST request using the Url property and the specified text.
The characters of the text are encoded using the given encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PutFile(path)
- Performs an HTTP PUT request using the Url property and data from the specified file.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PutText(text)
- Performs an HTTP PUT request using the Url property and the specified text.
The characters of the text are encoded using UTF-8 encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The responseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- PutTextWithEncoding(text,encoding)
- Performs an HTTP PUT request using the Url property and the specified text.
The characters of the text are encoded using the given encoding.
If the SaveResponse property is true, the response will be saved in a file and the GotFile event will be triggered. The ResponseFileName property can be used to specify the name of the file.
If the SaveResponse property is false, the GotText event will be triggered.
- UriDecode(text)
- Decodes the encoded text value so that the values aren’t URL encoded anymore.
- UriEncode(text)
- Encodes the given text value so that it can be used in a URL.
- XMLTextDecode(XmlText)
- Decodes the given XML string to produce a list structure.
<tag>string</tag>
decodes to a list that contains a pair of tag and string. More generally, if obj1, obj2, … are tag-delimited XML strings, then<tag>obj1 obj2 ...</tag>
decodes to a list that contains a pair whose first element is tag and whose second element is the list of the decoded obj’s, ordered alphabetically by tags.Examples:
<foo><123/foo>
decodes to a one-item list containing the pair(foo 123)
<foo>1 2 3</foo>
decodes to a one-item list containing the pair(foo "1 2 3")
<foo>1 2 3</foo><bar>456</bar>
decodes to a list containing the pair(a X)
where X is a 2-item list that contains the pair(bar 123)
and the pair(foo "1 2 3")
.
If the sequence of obj’s mixes tag-delimited and non-tag-delimited items, then the non-tag-delimited items are pulled out of the sequence and wrapped with a “content” tag. For example, decoding
<bar>456</bar>many<foo>1 2 3</foo>apples
is similar to above, except that the list X is a 3-item list that contains the additional pair whose first item is the string “content”, and whose second item is the list (many, apples). This method signals an error and returns the empty list if the result is not well-formed XML. - XMLTextDecodeAsDictionary(XmlText)
- Decodes the given XML string to produce a dictionary structure. The dictionary includes the
special keys
$tag
,$localName
,$namespace
,$namespaceUri
,$attributes
, and$content
, as well as a key for each unique tag for every node, which points to a list of elements of the same structure as described here.The
$tag
key is the full tag name, e.g., foo:bar. The$localName
is the local portion of the name (everything after the colon:
character). If a namespace is given (everything before the colon:
character), it is provided in$namespace
and the corresponding URI is given in$namespaceUri
. The attributes are stored in a dictionary in$attributes
and the child nodes are given as a list under$content
.More Information on Special Keys
Consider the following XML document:
<ex:Book xmlns:ex="http://example.com/"> <ex:title xml:lang="en">On the Origin of Species</ex:title> <ex:author>Charles Darwin</ex:author> </ex:Book>
When parsed, the
$tag
key will be"ex:Book"
, the$localName
key will be"Book"
, the$namespace
key will be"ex"
,$namespaceUri
will be"http://example.com/"
, the$attributes
key will be a dictionary{}
(xmlns is removed for the namespace), and the$content
will be a list of two items representing the decoded<ex:title>
and<ex:author>
elements. The first item, which corresponds to the<ex:title>
element, will have an$attributes
key containing the dictionary{"xml:lang": "en"}
. For eachname=value
attribute on an element, a key-value pair mappingname
tovalue
will exist in the$attributes
dictionary. In addition to these special keys, there will also be"ex:title"
and"ex:author"
to allow lookups faster than having to traverse the$content
list.


Polynomial Regression
Select the degree of the polynomial function you want to use for regression (default is 3)


Make a budget!
Page quantities:
I need a script JS?
Layout:
I need a layout
I already have a layout
Deadline
R$ 0,00
Enviar


The Atlanta Hawks’ 2019-2020 City threads pay homage to “The Peach State.”
It appears as though the Boston Celtics leaned into their Irish roots with their latest jerseys.
While the Brooklyn Nets have yet to release their City jerseys and no photos have been leaked, it appears as though the team’s 2019-2020 City jerseys will pay homage to Brooklyn native The Notorious B.I.G.
The Chicago Bulls went with the Bull logo, baby blue primary color, and red lining for their City unis.
A leak of the Cleveland Cavaliers’ City threads shows a unique “Cle” design with stripes along the sides.
The Dallas Mavericks are throwing it back to the ’90s with their new jerseys.
The Denver Nuggets’ existing rainbow skyline design pops a bit more on this year’s black base.
The Detroit Pistons’ new look is somewhat reminiscent of FC Barcelona jerseys.
The Golden State Warriors opted for a black and blue version of their classic City threads.
The Rockets’ City jerseys are inspired by Houston’s connection to NASA.
The Los Angeles Clippers channeled a newspaper-esque typeface for their City jerseys.
A leaked photo of the Los Angeles Lakers’ version, meanwhile, shows block letters and white stars down the sides.
The Miami Heat are sticking with their Vice jerseys but swapping out the black base for a powder blue version.
The Milwaukee Bucks are leaning into their “Cream City” moniker for their new unis.
Like a number of other teams, the Minnesota Timberwolves are also going with baby blue for their City jerseys this year.
The Thunder’s City jerseys were designed to honor those killed in the Alfred P. Murrah Federal Building bombing in Oklahoma City 25 years ago.
The Orlando Magic drew on the Sunshine State’s citrus fields for its City threads.
The Sixers opted for a classic callback to Philadelphia’s constitutional roots.
Phoenix went with Spanish “Los Suns” and “Somos PHX” jerseys.
The Portland Trail Blazers went for a redesign of their well-worn “ripcity” uniforms.
The Sacramento Kings are switching it up from their usual purple and white colors to a deep red.
The reigning champion Toronto Raptors went with black and gold threads for their City jerseys.
The Utah Jazz are sticking with their red, orange, and yellow City jerseys from the past two seasons.
The Washington Wizards brought back their stars and stripes jerseys for the City rollout.
Now check out the highest-paid coaches in college football:


1 write to M3PRunspaceStateChangedEvent
System.Management.Automation (1)
utils\tracing\TracingGen.cs (1)
182
M3PRunspaceStateChangedEvent
= new EventDescriptor(0xb023, 0x1, 0x11, 0x5, 0x14, 0x6, (long)0x4000000000000200);
1 reference to M3PRunspaceStateChangedEvent
System.Management.Automation (1)
utils\tracing\TracingGen.cs (1)
709
WriteEvent(
M3PRunspaceStateChangedEvent
, runspaceId, newState, oldState);


The initial innovations of the first Wunderlist app were monumental to the definition of what an app could do to be helpful in a persons life. Wunderlist lifted the to do list to an art form of a fully functional self management assistant. With our innovation came popularity and more coordination features.
Our application, Wunderlist 2.0 is based on a revival of the original Wunderlist with some additions that aid in the coordinations of teams for small organizations. It will have the simplicity you love with the ability to coordinate your actions amongst your friends or work teams if needed. Get Organized, Capture Details, Enhance Communication, Track time and Make Progress.


Reports To Transform Your Practice
Focus more time on enhancing your advisory services and building client value across your practice.
Tools To Transform Your Practice
Grow Client Relationships
Free up more time to focus on building closer client relationships, ensuring the client of today is the client for many years to come.
Be that trusted adviser that the business owner wants to work with.
Boost Advisory Revenues
React to a changing market where compliance fees are falling and reduce the time it takes to turn the numbers into insights and action.
Add tangible and immediate value to your clients and prospects.
Attract New Clients
Meet the changing needs of clients. Appeal to businesses who are looking for an accountant that embraces modern technology.
Transform data into visionary business advice through visualised reports, charts and graphs.
How It Works
Our Favourite Features
White Labelling
Add your logo and colours and make Cascade50 your own.
Accessible
Instant access to your clients' data from across the globe.
Security
Two factor authentication available, ensuring all data is protected.
Simple
No training required with just a 5 minute setup.
Customisation
Request dashboards bespoke to your clients' needs.
Contact Us
Talk it through with a member of our very friendly team. We'll show you what the dashboards can do and how we can help your practice.


Warehouse Chief Ranspo:
The inspector will be here in two days! We're running out of time! In fact, we've no time at all! Hurry back with a secret recipe from Jonas!
"Uh... who is Jonas?"


Thomas Jefferson Model UN & OAS
"Building Bridges"
A Letter From Our President
For over 20 years, Instituto Thomas Jefferson has hosted several UN Model’s in Mexico City and is about to go for its eighth edition on its Queretaro campus. It has been a very ambitious journey from the first year until today, and it grows larger every year. Last year, we had the honor of hosting a pioneer model that included both simulations of the United Nations and the Organization of the American States. It was an aspiring step and a successful achievement; however, this year we are aiming even higher. With competitive and quality committees, as well as social spaces to meet new people from all over Mexico and other countries, this year’s secretariat promises to do its best to make TJMUN & OAS 2016 the most enriching experience for delegates.
High school students get engaged in issues currently debated by world leaders, while developing leadership skills such as diplomacy, cooperation, debate, critical thinking, empathy and innovation. This increases the delegate's knowledge and broadens his/her point of view, not only during the debate, but in the whole experience of the model, on very important issues such as climate change, the fight against poverty, war, and the urge of having sustainable economies around the world.
On behalf of the Secretariat of TJMUN & OAS 2016 and our entire staff, I hope you can join us in December. Should you have any inquiries, don’t hesitate to contact us through<EMAIL_ADDRESS>On our website, you will find all the information you need about committees or any other specific information about the school and Queretaro.
I’m looking forward to meeting you this December at TJMUN & OAS 2016.
Sincerely, Humberto G. Salinas President TJMUN & OAS 2016


{% extends "layouts/base.html" %} {# ~~Dashboard:Template~~ #} {# we're potentially going need this in a few places in inherited files, so lets just put it here #} {# ~~-> EditorGroup:Model ~~ #} {% set managed_groups, maned_assignments = maned_of() %} {% set editor_of_groups, editor_of_assignments = editor_of() %} {% set associate_of_groups, associate_of_assignments = associate_of() %} {# ~~Dashboard:Template~~ #} {% block base_content %}
{# global site note #} {% if config.get("SITE_NOTE_ACTIVE", False) and not request.cookies.get(config.get("SITE_NOTE_KEY")) %} {% include config.get("SITE_NOTE_TEMPLATE") %} {% endif %}


| Capsule Name | Total Items | In Stock | Category | ||
|---|---|---|---|---|---|
| 1. Shrimp & Veggie Stir-Fry | 14 | 8 | Recipe | ||
| 2. Cocktail Dress | 1 | 1 | New Year's Eve | ||
| 3. Shed Project | 8 | 2 | Project | ||
| 4. (Grandma's) Spaghetti | 4 | 3 | Recipe | ||
| 5. Danny's Wedding | 16 | 4 | Special Event | ||
| 6. Oatmeal Raisen Muffins | 8 | 7 | Recipe | ||
| 7. New Year's Eve | 22 | 16 | Special Event | ||
| 8. Birthday Cake | 12 | 12 | Karen's Birthday |
| 1. Recipe | |
| 2. Outfit | |
| 3. Cleaning | |
| 4. Linens | |
| 5. Garage | |
| 6. Project | |
| 7. Special Event | |
| 8. Karen's Birthday | |
| 9. New Year's Eve |


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--com.milk.objed.AutoUpdater
An AutoUpdater
is used to cause a set of editors to be told
to update themselves at a regular basis.
| Nested Class Summary | |
private class |
AutoUpdater.UpdateRunnable
This class is used as the Runnable which fires off
all the update requests. |
| Field Summary | |
private java.util.Vector |
myEditors
the list of editors to update |
private int |
myFrequency
the frequency (in msec) to update, or 0 to stop |
private boolean |
myIsScheduled
true if the TimedRun is currently scheduled |
private int |
myLength
the length of the editors list |
private TimedRun |
myTimedRun
the TimedRun used to fire the update events |
| Constructor Summary | |
AutoUpdater()
Construct a new AutoUpdater , initially-empty and
stopped. |
| Method Summary | |
void |
add(Editor editor)
Add an editor to update. |
void |
remove(Editor editor)
Remove an editor that was previously added with addEditor() . |
private void |
schedule()
Schedule or cancel the runnable, as appropriate. |
void |
setFrequency(int frequency)
Set the frequency of updating. |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
private java.util.Vector myEditors
private int myLength
private int myFrequency
private TimedRun myTimedRun
TimedRun
used to fire the update events
private boolean myIsScheduled
TimedRun
is currently scheduled
| Constructor Detail |
public AutoUpdater()
AutoUpdater
, initially-empty and
stopped.
| Method Detail |
public void add(Editor editor)
editor
- the editor to addpublic void remove(Editor editor)
addEditor()
.
editor
- the editor to removepublic void setFrequency(int frequency)
frequency
- >= 0; the frequency (in msec) to update atprivate void schedule()
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


MBTI 8 기능…….
MBTI의 8가지 기능에 대해서
The Functions
기능들
There are two posts on personality theory that I recommend you start off with. The first is an introduction to personality type theory and “the functional stack.” It explains, among other things, how we determine the four functions that make up each personality type’s functional stack. The second post, Rethinking Judging & Perceiving in IPs & IJs, builds on the first and seeks to clarify some of the confusion relating to Judging and Perceiving in introverted types.
당신에게 처음 읽기 좋은 추천하는 두 개의 성격 이론 글이 있다. 첫번쨰는 성격이론의 소개 그리고 기능의 스택이다. 이것을 설명하자면 , 각각 성격 유형에 따른 기능의 스택으로 구성된 4가지 기능들을 어떻게 우리가 결정하는지를 설명하고 있다. 두번쨰 글은, IPs & IJs 유형에서의 판단과 인식에 대한 상고를 토대로 세우고, 내향 유형의 판단, 인식과 관련된 결론에 대해서 분류를 찾을 것이다.
-
The Eight Functions
-
8 가지 기능들
It is also important for any student of typology to understand the difference between the preferences (E, I, S, N, T, F, J, P) and the functions (see below). For the most thorough and accurate understanding of your personality type, I generally recommend focusing on understanding the functions and the role they play in your type’s functional stack. cognitive functionsA. Overview of the Eight Functions
어떤 연구의 유형 분류 체계에서도 선호와 기능들에 대한 차이점을 이해하는 것은 중요하다. 아주 철두 철미하고 정확하게 당신의 유형에 대해서 이해하는 것에 대해서는 , 나는 일반적으로 당신 유형의 기능들과 당신 유형의 기능적인 스택에 대해 이해하는데 집중하길 추천한다.
-
Introverted Intuition (Ni)
-
Extraverted Intuition (Ne)
-
Introverted Thinking (Ti)
-
Extraverted Thinking (Te)
-
Introverted Sensing (Si)
-
Extraverted Sensing (Se)
-
Introverted Feeling (Fi)
-
Extraverted Feeling (Fe)
-
내향 직관 (Ni)
-
외향 직관 (Ne)
-
내향 사고 (Ti)
-
외향 사고 (Te)
-
내향 감각 (Si)
-
외향 감각 (Se)
-
내향 감정 (Fi)
-
외향 감정 (Fe)
II. The Inferior Function
II. 열등 기능
The inferior function is another important piece of the personality puzzle. It is much more powerful and influential than we realize, unconsciously influencing our decision-making on a regular basis.
열등 기능은 성격 퍼즐의 또다른 중요한 부분이다. 무의식적으로 우리가 일반적인 기반으로써 의사 결정하는데 영향을 주는 열등기능은 우리가 알고 있는 것보다 더 강력하게 영향을 끼친다.
Overview of the Inferior Function 열등 기능 미리보기
8 기능들 개요
The Eight Functions (Typology 201)
By Dr. A.J. Drenth
In Typology 101, we provided an overview of the eight Myers-Briggs preferences (E, I, S, N, T, F, J, P). While the preferences can be helpful for determining your personality type and gaining a basic understanding of the ingredients that make up the types, they do not give us the whole story. Among other things, we also need to explore the eight functions. In this post, we will do just that, providing an introduction and overview of the eight functions.
유형분류체계 101, 우리는 8가지 Myers-Briggs 선호들에 대한 개요를 보았다. 선호들이 당신의 성격 유형을 결정하고 유형을 구성하고 있는 근간에 대해서 기본적인 지식을 얻는데 도움을 주지만, 그 개요는 전체적인 이야기를 해주지는 않는다. 이 글에서는, 우리는 8가지 기능에 대한 소개와 개괄을 살펴볼 것이다.
According to Jung, Sensing, Intuition, Thinking, and Feeling can be directed inwardly (i.e., “introverted”) or outwardly (i.e., “extraverted”). When introverted, these functions are largely concealed and unobservable by others. When extraverted, they are more easily observed from without. Here is a list of the eight functions:
융에 따르면, 감각, 직관, 사고, 감정은 내부적, 외부적으로 연결되어 있다. 내향적일때, 이 기능들은 크게 숨겨지거나 또 다른 것들에 의해서 관찰 할 수가 없다. 외부적일때, 아주 쉽게 기능들은 관찰될수 있다. 여기 8가지 기능들이 있다.
-
Introverted Sensing (Si)
-
Introverted Intuition (Ni)
-
Introverted Thinking (Ti)
-
Introverted Feeling (Fi)
-
Extraverted Sensing (Se)
-
Extraverted Intuition (Ne)
-
Extraverted Thinking (Te)
-
Extraverted Feeling (Fe)
-
내향 감각 (Si)
-
내향 직관 (Ni)
-
내향 사고 (Ti)
-
내향 감정 (Fi)
-
외향 감각 (Se)
-
외향 직관 (Ne)
-
외향 사고 (Te)
-
외향 감정 (Fe)
-
Introverted (Si, Ni, Ti, Fi) & Extraverted Functions (Se, Ne, Te, Fe)
-
내향형 & 외향형
Just as all the extraverted personality types have certain traits in common, so too with the extraverted functions. Their first and most obvious commonality is their outward direction. They are also characteristically broad in their scope compared to the introverted functions (just as extraverts are more outgoing and expansive in their dealings than introverts). The introverted functions, by contrast, are narrower in scope (just as introverts are apt to have narrower or more focused interests or activities than extraverts). Whatever the introverted functions may lack in extensiveness, however, they make up for in depth.
단지 모든 외향 성격 유형들이 공통적으로 어떤 특징을 가지는 것처럼 외향 기능들도 그러하다. 그것들은 첫째도 가장 명백한 공통성은 외부 방향이라는 것이다. 외향 기능들은 개성적으로 내향 기능들과 비교하여 외향기능 범위가 크다.(단지 내향적인 사람보다 외향적인 사람은 더 사교적이고 광범위하다) 대조적으로 , 내향기능들은 , 좁은 범위를 가진다.(단지 외향적인 사람보다 관심이나 활동들이 좁고 집중되어있는 경향이 있다.)
Extraverted Functions
외향기능
-
Directed outwardly (observable by others)
-
Broad in scope; extensive
-
외부적으로 통제됨(외부에서 관찰된다.)
-
범위가 크다; 광범위함
-
Directed inwardly (concealed from others)
-
Narrow in scope; deep and intensive
-
내부적으로 통제됨 (외부로부터 감추어진)
-
좁은 범위; 깊고 집중적인
While we soon explore each of the eight functions in greater depth, here is a quick look at how this E-I difference manifests in the various functions:
-
Extraverted Sensing (Se) seeks extensive outward stimulation—new sights, sounds, tastes, experiences, etc.
-
Introverted Sensing (Si) draws on past personal experience, the “tried and true,” making it unnecessary to constantly seek new or broad experiences.
-
Extraverted Intuition (Ne) explores new ideas, patterns, and possibilities in the outside world. Since Ne springboards off existing ideas and theories, Ne types often read extensively in order to acquire a broad or diverse understanding.
-
Introverted Intuition (Ni) apprehends ideas, patterns, and perspectives that emerge within. INJs may feel less compelled to read extensively, since their source of N material is inwardly derived and divined.
-
Extraverted Thinking (Te) seeks to make external operations more rational and efficient. Its “standardized” methods can be broadly applied to make nearly any organization or enterprise more rational.
-
Introverted Thinking (Ti) is concerned with inner rationality and personal effectiveness. Its methods are more individualized and therefore less broadly applicable than those of Te.
-
Extraverted Feeling (Fe) surveys a breadth of human feeling. Its goal is to cultivate interpersonal harmony among people.
-
Introverted Feeling (Fi) is concerned with inner harmony. Whereas Fe focuses on interpersonal matters, Fi is intrapersonal. Its focus is on personal values, preferences, and feelings.
-
The Judging (Ti, Te, Fi, Fe) & Perceiving Functions (Si, Se, Ni, Ne)
우리는 곧 아주 깊게 각각 8가지 기능에 대해서 탐구할 동안, 다양한 기능에서 여기 어떻게 E-I가 차이점을 드러내는지 한눈에 보여준다.
-
외향 감정은 광범위한 외부의 새로운 시야, 소리, 맛, 경험 등에 대한 자극을 추구한다.
-
내향 직관은 개인적인 "시도와 사실"에 대한 과거의 경험에 의지한다. 새로운 끊임없이 새로운 것을 찾거나 넓은 경험은 불필요하다.
-
외향 직관은 외부 세계의 새로운 관념, 패턴, 가능성을 탐구한다. Ne는 존재하는 관념과 이론들을 넘어가려고 하기 떄문에, Ne 타입들은 종종 넓고 다양한 이를 얻기 위해서 광범위하게 인식한다.
-
내향 직관은 드러나는 관념들, 패턴들, 관점들을 잡아냅니다. INJs 유형들은 덜 광범위하게 인식하게 됨을 느낄지도 모른다. 왜냐하면 직관의 근원은 내부적으로 기인되어 있고 직감적으로 되어있다.
-
외향 사고는 더 합리적이고 효율적인 외부적인 조작들을 하기를 추구한다. 이것은 "표준화된" 방법들은 널리 가까운 어떤 조직이나 기업에서 합리적으로 널리 적용수 있는것이다.
-
외향 사고는 내부의 합리성과 개인적인 효율성에 연관짓는다. 이 방법은 더 개인되어있으며 그러므로 덜 외향사고보다 좁은 영역에서 적용할 수 있다.
-
외향 감정은 인간적인 감정에 깊이를 살핀다. 이 목표는 사람사이의 대인관계의 조화를 구축하는데 목표를 둔다.
-
내향 감정은 내부의 조화와 연관된다. 외향 감정은 대인관계의 문제에 치중하는 반면에 , 내향 감정은 개인적인 내의 것이다. 내향감정은 개인의 가치, 선호 ,느낌들에 있다.
The Judging (Ti, Te, Fi, Fe) & Perceiving Functions (Si, Se, Ni, Ne)
판단과(Ti, Te, Fi, Fe) & 인식 기능들(Si, Se, Ni, Ne)
We can also divide the eight functions according to whether they are Judging or Perceiving functions. Namely, the Thinking (Ti, Te) and Feeling (Fi, Fe) functions are Judging functions, while the Sensing (Si, Se) and Intuition (Ni, Ne) functions are considered Perceiving functions. The Perceiving functions are responsible for taking in or retrieving information. Observing birds, smelling flowers, reading novels, and recalling something from memory are examples of Perceiving activities. Unlike the Judging functions, the Perceiving functions are not concerned with actively shaping or controlling, but with absorbing life and information.
우리는 종종 판단과 인식의 기능에 따라서 8가지 기능들을 나눈다. 다시 말해서, 사고(Ti, Te)와 감정(Fi, Fe)의 기능들은 판단의 기능들이고 , 반면에 감각(Si, Se)과 직관(Ni, Ne)의 기능은 인식의 기능들이다. 인식기능들은 정보를 취하고 탐색하는 역할을 맡고 있다. 눈에 보이는 새들, 냄새나는 꽃, 읽고있는 소설들, 어떤 기억으로부터의 상기들은 인식 활동의 예이다. 판단기능 이와 같지 않게, 인식기능들은 활동적으로 형성 또는 통제되는 것과는 연관되지 않고 삶의 몰입하는 삶과 정보와 연관된다.
Perceiving functions
인식 기능들
The Judging functions allow us to make decisions and draw conclusions based on received information. They are related to a desire to control, predict, order, or otherwise actively shape the course of things. When using our Judging process, we often close ourselves off to new information (i.e., we shut down Perceiving) in our desire to move toward an answer, decision, or objective.
판단기능은
Judging functions
Having considered some important background information on the functions, I will now provide an overview of each of the eight functions (I also have written individual posts on each function, available through the links below, as well as our Functions Page). We will begin with a look at the four Perceiving functions and end with the four Judging functions.
Extraverted Intuition (Ne)
NP types use Extraverted Intuition (Ne) as their dominant or auxiliary function. The verbal expression of Ne amounts to something like “brainstorming aloud.” When orating, NPs may not always seem to “have a point” as they haphazardly move from one idea to the next. Ne is more divergent and expansive in nature than its introverted cousin, Ni. NPs feel compelled to outwardly explore all the options and possibilities, making it difficult for them to draw firm conclusions or make confident decisions. The divergent nature of Ne explains why NPs often seem random, distractible, quirky, or flighty. Ne types use their Si to recall what has been and then use their Ne to envision what could be. This orientation toward future possibilities gives Ne types a good nose for inventing, marketing, entrepreneurship, politics, journalism, etc.
Introverted Intuition (Ni)
NJ types use Introverted Intuition (Ni) as their dominant or auxiliary function. Unlike Ne, which expands the number of options or possibilities, Ni tends to work more convergently, producing a more singular and comprehensive vision or solution. The convergent capacities of Ni provides NJs a greater sense of confidence and conviction in moving forward, contributing to their effectiveness as theorists, leaders, problem solvers, and advisers. INJs often think by way of images rather than words. Their intuitions may manifest as gut feelings, hunches, symbols, dreams, or imagery. Because Ni does much of its work subconsciously, it is sometimes perceived as having a certain magical or prophetic quality. But Ni need not be considered in any way magical or mystical. Ni intuitions are generated from information provided by NJs’ other functions, particularly their Se, which gathers concrete data from the immediate environment that serves as raw material for their Ni. Like working a puzzle, Ni synthesizes Se pieces of information and generates an intuitive impression or interpretation of what is happening, as well as a sense of what might happen next. For more on Ne-Ni differences, see this post.
Extraverted Sensing (Se)
SPs types use Extraverted Sensing (Se) as either their dominant or auxiliary function. SPs are sensual, instinctual, and appetitive. They relish stimulation of their five senses—new sights, sounds, tastes, scents, movements, textures, etc. They are “sensation-seekers,” relishing novel experiences, material pleasures, and the thrill of action. ESPs are highly observant and attuned to the details of the world around them, especially in areas that interest them. As Extraverts, their preferences often change according to what is popular or trendy.
Introverted Sensing (Si)
SJ types use Introverted Sensing (Si) as either their dominant or auxiliary function. Despite their shared status as Sensors, SJs are quite different from SPs. SJs do not venture out seeking novel sensations, experiences, or material goods. Instead, they prefer a more routinized and predictable lifestyle, functioning more as “homebodies.” ISJs may also fail to notice external details to the degree exhibited among ESPs. Unlike SPs, who are oriented to the present moment and the current trends, SJs rely on information from the past to inform the present. They grow attached to past ways of doing things, compelling them to conserve and protect traditions or conventions. Because of their concern for the remembered past, Si might be considered more abstract and less concrete than Se is.
Extraverted Thinking (Te)
TJ types use Extraverted Thinking (Te) as their dominant or auxiliary function. Te involves the outward expression of rational judgments and opinions; TJs literally think (i.e., make judgments, conclusions, and decisions) aloud. Te is more fact-oriented than Ti is. STJs, in particular, see the world as composed of discrete, black-and-white parts. This allows them to institute clear definitions, objective standards, and measurable goals. While Ti is forever backtracking to question and clarify underlying ideas and assumptions, Te is more positivistic and forward-moving, working to improve definitions, plans, policies, classifications, procedures, etc. It carefully spells out how to get from here to there, using as many maps, labels, and instructions as necessary. The modern world, characterized by a snowballing of laws and bureaucracy, might be viewed as stemming from an unchecked Te.
Introverted Thinking (Ti)
TP types use Introverted Thinking (Ti) as their dominant or auxiliary function. Since Ti is introverted, TPs are reluctant to express their rational judgments outwardly. Ti is used to bring structure and order to TPs’ inner world. This inner structuring grants them a strong sense of inner control. Inwardly, TPs are highly self-disciplined, working to independently manage their thoughts in a way that allows them to better cope with life. TPs (especially NTPs) are less interested in working with facts than with ideas. Jung writes of the ITP: “His ideas have their origin not in objective data but in his subjective foundation.” ITPs are constantly digging into the background of their own thoughts in order to better understand their origins and to ensure their thinking is founded on clear and logical ideas. They see it pointless to try to build a system of thought on a dubious conceptual platform, making them slower than Te types to rush into experiments in order to discover more “facts.” This is especially true of NTPs, who find it easier to identify inconsistencies or logical shortcomings—to assert what is not true—than to identify and confidently assert what is true. While their skepticism is often broad and liberal, their positivism is minimal and conservative.
Extraverted Feeling (Fe)
FJ types use Extraverted Feeling (Fe) as their dominant or auxiliary function. FJs, especially EFJs, are quick to outwardly express their feelings, opinions, and grievances. Fe plays a prominent role in attuning to and empathizing with others’ emotions. It allows FJs to recreate another’s emotion state within themselves, allowing them to literally feel what the other person is feeling. FJs also work to meet others’ needs and to maintain harmony in the external environment. They ensure that everyone is getting along and is well cared for. At the same time, since Fe is an Extraverted Judging function, there are times when FJs are compelled to sacrifice external harmony for the sake of asserting their judgments. FJs also enjoy giving counsel and advice, especially with regard to people-related matters.
Introverted Feeling (Fi)
All FP types use Introverted Feeling (Fi) as their dominant or auxiliary function. Fi is directed inwardly, navigating and managing personal feelings and values on a largely independent basis. While Fe turns to others for emotional support and kinship, Fi deals with emotions more independently. When IFPs do opt to outwardly express their feelings and values, they often do so indirectly—through active (S), creative (N), or rational (Te) means. Fi also inspires FPs types to help the underserved. They can commonly be found helping the sick, the needy, children, and animals. They love to rescue those in need, such as by adopting pets from animal shelters. Moreover, Fi works to shape its own worldview—a personalized system of values—that can serve as a platform for self-understanding and decision-making. As is the case with TPs, this self-understanding grants FPs a strong sense of inner control. While FPs (especially IFPs) may feel they have little control over other people, they feel confident in regulating their own feelings, values, and actions.
A Recipe for Potion
Two fresh Burdockian leaves, harvested by the light of the teal moons…
Searching for Burdockian
Crawling through the twisted understory.. Press the btn:[OK] button when you are finished.


Boost Library Requirements and Guidelines
Introduction
This page describes requirements and guidelines for the content of a library submitted to Boost.
See the Boost Library Submission Process page for a description of the process involved.
Requirements
To avoid the frustration and wasted time of a proposed library being rejected, it must meet these requirements:
- The license must meet the license requirements below. Restricted licenses like the GPL and LGPL are not acceptable.
- The copyright ownership must be clear.
- The library should be generally useful.
- The library must meet the portability requirements below.
- The library should preferably meet the organization requirements below. But is only required to meet them after acceptance.
- The library must come reasonably close to meeting the Guidelines below.
- The author must be willing to participate in discussions on the mailing list, and to refine the library accordingly.
There's no requirement that an author read the mailing list for a time before making a submission. It has been noted, however, that submissions which begin "I just started to read this mailing list ..." seem to fail, often embarrassingly.
License requirements
The preferred way to meet the license requirements is to use the Boost Software License. See license information. If for any reason you do not intend to use the Boost Software License, please discuss the issues on the Boost developers mailing list first.
The license requirements:
- Must be simple to read and understand.
- Must grant permission without fee to copy, use and modify the software for any use (commercial and non-commercial).
- Must require that the license appear on all copies of the software source code.
- Must not require that the license appear with executables or other binary uses of the library.
- Must not require that the source code be available for execution or other binary uses of the library.
- May restrict the use of the name and description of the library to the standard version found on the Boost web site.
Portability requirements
- A library's interface must portable and not restricted to a particular compiler or operating system.
- A library's implementation must if possible be portable and not restricted to a particular compiler or operating system. If a portable implementation is not possible, non-portable constructions are acceptable if reasonably easy to port to other environments, and implementations are provided for at least two popular operating systems (such as UNIX and Windows).
- A library runs on at least two C++ compilers implementing the latest ISO C++ standard.
- There is no requirement that a library run on C++ compilers which do not conform to the ISO standard.
- There is no requirement that a library run on any particular C++ compiler. Boost contributors often try to ensure their libraries work with popular compilers. The boost/config.hpp configuration header is the preferred mechanism for working around compiler deficiencies.
Since there is no absolute way to prove portability, many boost submissions demonstrate practical portability by compiling and executing correctly with two different C++ compilers, often under different operating systems. Otherwise reviewers may disbelieve that porting is in fact practical.
Ownership
Are you sure you own the library you are thinking of submitting? "How to Copyright Software" by MJ Salone, Nolo Press, 1990 says:
Doing work on your own time that is very similar to programming you do for your employer on company time can raise nasty legal problems. In this situation, it's best to get a written release from your employer in advance.
Place a copyright notice in all the important files you submit. Boost won't accept libraries without clear copyright information.
Organization
The quality of the Boost libraries is not just about the APIs and code design. But also about presenting a consistent view to users of the libraries as a whole. Upon acceptance libraries must adhere to this directory and file structure:
| Sub-directory or file | Contents | Required |
|---|---|---|
build |
Library build files such as a Jamfile, IDE projects, Makefiles, Cmake files, etc. | Required if the library has sources to build. |
config |
Files used for build-time configuration checks. This directory may contain source files and build system scripts to be used when building the library, tests or examples to check if the target system satisfies certain conditions. For example, a check may test if the compiler implements a certain feature, or if the target system supports a certain API. | Optional. |
doc |
Sources to build with and built documentation for the library. If the library needs to build documentation from non-HTML files this location must be buildable with Boost Build. | Required for all libraries. |
doc/html |
Documentation (HTML) files. | Required for all libraries with pregenerated documentation. And generated documentation must be generated here. |
example |
Sample program files. | Required if library has sample files. Which is highly recommended. |
index.html |
Redirection to HTML documentation. See "Redirection" for a template for this file. | Required for all libraries. |
include/boost/library |
Header files for the library. | Required for all libraries. |
meta |
Meta-data about the library. | Required for all libraries. |
meta/libraries.json |
A JSON file containing information about the library used to generate website and documentation for the Boost C++ Libraries collection. | Required for all libraries. |
meta/explicit-failures-markup.xml |
XML file describing expected test failures, used to generate the test report. | Optional |
src |
Source files which must be compiled to build the library. | Required if the library has source files to build. |
test |
Regression or other test programs or scripts. This is the only location considered for automated testing. If you have additional locations that need to be part of automated testing it is required that this location refer to the additional test locations. | Required for all libraries. |
tools |
Tools used, or offered, by the library. The structure within this is up to the library, but it's recommended to use similar structure as a regular Boost library or tool. | Required for libraries that have runable tools. |
Integration
Once a library is accepted as part of the Boost C++ Libraries it is required that it integrate properly into the development, testing, documentation, and release processes. This integration increases the eventual quality of all the libraries and is integral to the expected quality of the whole of the Boost C++ Libraries from users. In addition to the organization requirements above the following integration is required:
Building Sources
The library needs to provide a Boost Build project that the user, and the top level Boost project, can use to build the library if it has sources to build. The Jamfile for the source build needs to minimally declare the project, the library target(s), and register the target(s) for installation. For example:
project boost/my_lib ; lib boost_my_lib : a.cpp ; boost-install boost_my_lib ;
Testing
The library needs to provide a Boost Build project that the user, and the root Boost test script, can use to build and run the tests for the library. The testing build project must reside in the project-root/test directory and must be buildable from this or another directory (for example, b2 libs/library/test from the Boost root must work.)
An example test/Jamfile is given below:
import testing ; run default_constructor.cpp ; run copy_constructor.cpp ; compile nested_value_type.cpp ; compile-fail invalid_conversion_1.cpp ;
WARNING: This is the only location considered for testing by the top level testing script. If you want to test additional locations you must declare such that they are built as dependencies or by using build-project.
If the library requires a level of C++ conformance that precludes certain compilers or configurations from working, it's possible (and recommended) to declare these requirements in the test Jamfile so that the tests aren't run, to conserve test resources, as given in the example below:
import testing ; import ../../config/checks/config : requires ; project : requirements [ requires cxx11_variadic_templates cxx11_template_aliases ] ; run cpp11_test.cpp ;
For more information, see the documentation of Boost.Config.
Building Documentation
The library needs to provide a Boost Build project for building the documentation for the library. The project-root/doc project is the only location refered to by the top level documentation build scripts and the release building scripts. The documentation build project must have the following two features:
- Define a boostdoc target. This target should
likely be an alias that looks roughly like:
alias boostdoc : my_boostbook_target : : : <implicit-dependency>my_boostbook_target ;
But if your project doesn't integrate into the global documentation book you can use an empty alias like:
alias boostdoc ;
- The project must default to building standalone documentation if it has any. The release scripts build this default so as to guarantee all projects have up to date documentation.
Guidelines
Please use these guidelines as a checklist for preparing the content a library submission. Not every guideline applies to every library, but a reasonable effort to comply is expected.
Backwards Compatibility
Boost libraries generally have a large and diverse user base. To ensure successful transitions from old APIs to newer APIs under those circumstances, library authors are encouraged to follow a few guidelines when introducing breaking changes in their library:- Non-breaking changes can be done without restriction.
- Small breaking changes can be made, but users should be given notice a few releases before the change is published. Most breaking changes fall into this category.
-
For large breaking changes
with a migration path from the old API to the new API (for example boost::filesystem v2 to v3), the new API should be introduced in a separate directory/namespace, and users should be noticed and given a few releases to move over. The old API can be removed after some time. -
For large breaking changes
without a migration path (for example boost::spirit v2 to v3), the new API should be provided in a separate directory/namespace, and the old API should be preserved (because there's no migration path). Removing the API should be considered the same as removing a Boost library, which can be done but needs a more extensive deprecation period. - Large breaking changes that are equivalent to a redesign or rewrite of the library should be treated as a new library and a formal review (or at least a mini review) is encouraged.
Design and Programming
Aim first for clarity and correctness; optimization should be only a secondary concern in most Boost libraries.
Aim for ISO Standard C++. Than means making effective use of the standard features of the language, and avoiding non-standard compiler extensions. It also means using the C++ Standard Library where applicable.
Headers should be good neighbors. See the header policy. See Naming consistency.
Follow quality programming practices. See, for example, "Effective C++" 2nd Edition, and "More Effective C++", both by Scott Meyers, published by Addison Wesley.
Use the C++ Standard Library or other Boost libraries, but only when the benefits outweigh the costs. Do not use libraries other than the C++ Standard Library or Boost. See Library reuse.
Read Implementation Variation to see how to supply performance, platform, or other implementation variations.
Browse through the Best Practices Handbook for ideas and links to source code in existing Boost libraries.
Read the guidelines for libraries with separate source to see how to ensure that compiled link libraries meet user expectations.
Use the naming conventions of the C++ Standard Library (See Naming conventions rationale):
- Names (except as noted below) should be all lowercase, with words separated by underscores.
- Acronyms should be treated as ordinary names (e.g.
xml_parser
instead ofXML_parser
). - Template parameter names begin with an uppercase letter.
- Macro (gasp!) names all uppercase and begin with BOOST_.
Choose meaningful names - explicit is better than implicit, and readability counts. There is a strong preference for clear and descriptive names, even if lengthy.
Use exceptions to report errors where appropriate, and write code that is safe in the face of exceptions.
Avoid exception-specifications. See exception-specification rationale.
Provide sample programs or confidence tests so potential users can see how to use your library.
Provide a regression test program or programs which follow the Test Policies and Protocols.
Although some boost members use proportional fonts, tabs, and unrestricted line lengths in their own code, boost's widely distributed source code should follow more conservative guidelines:
- Use fixed-width fonts. See fonts rationale.
- Use spaces rather than tabs. See tabs rationale.
- Limit line lengths to 80 characters.
End all documentation files (HTML or otherwise) with a copyright message and a licensing message. See the license information page for the preferred form.
Begin all source files (including programs, headers, scripts, etc.) with:
- A comment line describing the contents of the file.
- Comments describing copyright and licensing: again, the preferred form is indicated in the license information page
- Note that developers are allowed to provide a copy of
the license text in
LICENSE_1_0.txt
,LICENSE.txt
orLICENSE
file within repositories of their libraries. - A comment line referencing your library on the Boost web
site. For example:
// See https://www.boost.org/libs/foo for library home page.
Where
foo
is the directory name (see below) for the library. As well as aiding users who come across a Boost file detached from its documentation, some of Boost's automatic tools depend on this comment to identify which library header files belong to.
Assertions: If you want to add runtime
assertions to your code (you should!), avoid C's
assert
macro and use Boost's
BOOST_ASSERT
macro (in
boost/assert.hpp
) instead. It is more
configurable. Use BOOST_ASSERT
in public headers
and in library source code (for separately compiled libraries).
Use of C's assert
macro is ok in examples and in
documentation.
Make sure your code compiles in the presence of the
min()
and max()
macros. Some platform
headers define min()
and max()
macros
which cause some common C++ constructs to fail to compile. Some
simple tricks can protect your code from inappropriate macro
substitution:
- If you want to call
std::min()
orstd::max()
:- If you do not require argument-dependent look-up, use
(std::min)(a,b)
. - If you do require argument-dependent look-up, you
should:
#include <boost/config.hpp>
- Use
BOOST_USING_STD_MIN();
to bringstd::min()
into the current scope. - Use
min BOOST_PREVENT_MACRO_SUBSTITUTION (a,b);
to make an argument-dependent call tomin(a,b)
.
- If you do not require argument-dependent look-up, use
- If you want to call
std::numeric_limits<int>::max()
, use(std::numeric_limits<int>::max)()
instead. - If you want to call a
min()
ormax()
member function, instead to doingobj.min()
, use(obj.min)()
. - If you want to declare or define a function or a member
function named
min
ormax
, then you must use theBOOST_PREVENT_MACRO_SUBSTITUTION
macro. Instead of writingint min() { return 0; }
you should writeint min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
This is true regardless if the function is a free (namespace scope) function, a member function or a static member function, and it applies for the function declaration as well as for the function definition.
Filenames
Naming requirements ensure that file and directory names are relatively portable, including to ISO 9660:1999 (with extensions) and other relatively limited file systems. Superscript links are provided to detailed rationale for each choice.
- Names must contain only
lowercase1 ASCII letters
(
'a'
-'z'
), numbers ('0'
-'9'
), underscores ('_'
), hyphens ('-'
), and periods ('.'
). Spaces are not allowed2. - Directory names must not contain periods
(
'.'
)3. - The first and last character of a file name must not be a
period (
'.'
)4. - The first character of names must not be a hyphen
(
'-'
)5. - The maximum length of directory and file names is 31 characters6.
- The total path length must not exceed 207 characters7.
Other conventions ease communication:
- Files intended to be processed by a C++ compiler as part of a translation unit should have a three-letter filename extension ending in "pp". Other files should not use extensions ending in "pp". This convention makes it easy to identify all of the C++ source in Boost.
- All libraries have at their highest level a primary directory named for the particular library. See Naming consistency. The primary directory may have sub-directories.
Redirection
The primary directory should always contain a file named index.html. Authors have requested this so that they can publish URL's in the form https://www.boost.org/libs/lib-name with the assurance a documentation reorganization won't invalidate the URL. Boost's internal tools are also simplified by knowing that a library's documentation is always reachable via the simplified URL.
The primary directory index.html
file should
just do an automatic redirection to the doc/html
subdirectory:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">   <title>Boost.Name Documentation</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="refresh" content="0; URL=doc/html/index.html" />   Automatic redirection failed, please go to doc/index.html
Naming consistency
As library developers and users have gained experience with Boost, the following consistent naming approach has come to be viewed as very helpful, particularly for larger libraries that need their own header subdirectories and namespaces.
Here is how it works. The library is given a name that describes the contents of the library. Cryptic abbreviations are strongly discouraged. Following the practice of the C++ Standard Library, names are usually singular rather than plural. For example, a library dealing with file systems might chose the name "filesystem", but not "filesystems", "fs" or "nicecode".
- The library's primary directory (in parent boost-root/libs) is given that same name. For example, boost-root/libs/filesystem.
- The library's primary header directory (in boost-root/libs/name/include) is given that same name. For example, boost-root/libs/filesystem/boost/filesystem.
- The library's primary namespace (in parent ::boost) is given that same name, except when there's a component with that name (e.g., boost::tuple), in which case the namespace name is pluralized. For example, ::boost::filesystem.
When documenting Boost libraries, follow these conventions (see also the following section of this document):
- The library name is set in roman type.
- The library name is capitalized.
- A period between "Boost" and the library name (e.g., Boost.Bind) is used if and only if the library name is not followed by the word "library".
- The word "library" is not part of the library name and is therefore lowercased.
Here are a few examples of how to apply these conventions:
- Boost.Bind was written by Peter Dimov.
- The Boost Bind library was written by Peter Dimov.
- I regularly use Bind, a Boost library written by Peter Dimov.
Documentation
Even the simplest library needs some documentation; the amount should be proportional to the need. The documentation should assume the readers have a basic knowledge of C++, but are not necessarily experts.
The format for documentation should be HTML, and should not require an advanced browser or server-side extensions. Style sheets are acceptable. ECMAScript/JavaScript is discouraged. The documentation entry point should always be a file named index.html; see Redirection.
There is no single right way to do documentation. HTML documentation is often organized quite differently from traditional printed documents. Task-oriented styles differ from reference oriented styles. In the end, it comes down to the question: Is the documentation sufficient for the mythical "average" C++ programmer to use the library successfully?
Appropriate topics for documentation often include:
- General introduction to the library. The introduction
particularly needs to include:
- A very high-level overview of what the library is good for, and perhaps what it isn't good for, understandable even by those with no prior knowledge of the problem domain.
- The simplest possible ("hello world") example of using the library.
- Tutorial covering basic use cases.
- Reference documentation:
- Description of each class.
- Relationship between classes.
- For each function, as applicable, description, requirements (preconditions), effects, post-conditions, returns, and throws.
- Discussion of error detection and recovery strategy.
- How to compile and link.
- How to test.
- Version or revision history.
- Rationale for design decisions. See Rationale rationale.
- Acknowledgements. See Acknowledgments rationale.
If you need more help with how to write documentation you can check out the article on Writing Documentation for Boost.
Rationale
Rationale for some of the requirements and guidelines follows.
Exception-specification rationale
Exception specifications [ISO 15.4] are sometimes coded to indicate what exceptions may be thrown, or because the programmer hopes they will improve performance. But consider the following member from a smart pointer:
T& operator*() const throw() { return *ptr; }
This function calls no other functions; it only manipulates fundamental data types like pointers Therefore, no runtime behavior of the exception-specification can ever be invoked. The function is completely exposed to the compiler; indeed it is declared inline Therefore, a smart compiler can easily deduce that the functions are incapable of throwing exceptions, and make the same optimizations it would have made based on the empty exception-specification. A "dumb" compiler, however, may make all kinds of pessimizations.
For example, some compilers turn off inlining if there is an exception-specification. Some compilers add try/catch blocks. Such pessimizations can be a performance disaster which makes the code unusable in practical applications.
Although initially appealing, an exception-specification tends to have consequences that require very careful thought to understand. The biggest problem with exception-specifications is that programmers use them as though they have the effect the programmer would like, instead of the effect they actually have.
A non-inline function is the one place a "throws nothing" exception-specification may have some benefit with some compilers.
Naming conventions rationale
The C++ standard committee's Library Working Group discussed this issue in detail, and over a long period of time. The discussion was repeated again in early boost postings. A short summary:
- Naming conventions are contentious, and although several are widely used, no one style predominates.
- Given the intent to propose portions of boost for the next revision of the C++ standard library, boost decided to follow the standard library's conventions.
- Once a library settles on a particular convention, a vast majority of stakeholders want that style to be consistently used.
Source code fonts rationale
Dave Abrahams comments: An important purpose (I daresay the primary purpose) of source code is communication: the documentation of intent. This is a doubly important goal for boost, I think. Using a fixed-width font allows us to communicate with more people, in more ways (diagrams are possible) right there in the source. Code written for fixed-width fonts using spaces will read reasonably well when viewed with a variable-width font, and as far as I can tell every editor supporting variable-width fonts also supports fixed width. I don't think the converse is true.
Tabs rationale
Tabs are banned because of the practical problems caused by tabs in multi-developer projects like Boost, rather than any dislike in principle. See mailing list archives. Problems include maintenance of a single source file by programmers using tabs and programmers using spaces, and the difficulty of enforcing a consistent tab policy other than just "no tabs". Discussions concluded that Boost files should either all use tabs, or all use spaces, and thus the decision to stick with spaces for indentation.
Directory and File Names rationale
1. Some legacy file systems require single-case names. Single-case names eliminate casing mistakes when moving from case-insensitive to case-sensitive file systems.
2. This is the lowercase portion of the POSIX portable filename character set. To quote the POSIX standard, "Filenames should be constructed from the portable filename character set because the use of other characters can be confusing or ambiguous in certain contexts."
3. Strict implementations of ISO 9660:1999 and some legacy operating systems prohibit dots in directory names. The need for this restriction is fading, and it will probably be removed fairly soon.
4. POSIX has special rules for names beginning with a period. Windows prohibits names ending in a period.
5. Would be too confusing or ambiguous in certain contexts.
6. We had to draw the line somewhere, and so the limit imposed by a now obsolete Apple file system was chosen years ago. It still seems a reasonable limit to aid human comprehension.
7. ISO 9660:1999.
ECMAScript/JavaScript rationale
Before the 1.29.0 release, two Boost libraries added ECMAScript/JavaScript documentation. Controversy followed (see mailing list archives), and the developers were asked to remove the ECMAScript/JavaScript. Reasons given for banning included:
- Incompatible with some older browsers and some text based browsers.
- Makes printing docs pages difficult.
- Often results in really bad user interface design.
- "It's just annoying in general."
- Would require Boost to test web pages for ECMAScript/JavaScript compliance.
- Makes docs maintenance by other than the original developer more difficult.
Please conside those reasons if you decide that JavaScript is something you must use. In particular please keep in mind that the Boost community is not responsible for testing your use of JavaScript. And hence it is up to you to ensure that the above issues are fully resolved in your use case.
ECMAScript/JavaScript use is allowed but discouraged for the reasons above.
Rationale rationale
Rationale is defined as "The fundamental reasons for something; basis" by the American Heritage Dictionary.
Beman Dawes comments: Failure to supply contemporaneous rationale for design decisions is a major defect in many software projects. Lack of accurate rationale causes issues to be revisited endlessly, causes maintenance bugs when a maintainer changes something without realizing it was done a certain way for some purpose, and shortens the useful lifetime of software.
Rationale is fairly easy to provide at the time decisions are made, but very hard to accurately recover even a short time later.
Acknowledgements rationale
As a library matures, it almost always accumulates improvements suggested to the authors by other boost members. It is a part of the culture of boost.org to acknowledge such contributions, identifying the person making the suggestion. Major contributions are usually acknowledged in the documentation, while minor fixes are often mentioned in comments within the code itself.