package main
type Box struct {
Height int
Width int
}
// It's a kind of constructor
func NewBox(height int, width int) (*Box, error) {
if height <= 0 || width <= 0 {
return nil, errors.New("params must be greater than zero")
}
return &Box{height, width}, nil
}
func main() {
b, err := NewBox(1, 2)
if err != nil {
...
}
}
Golang. A simple concept of a constructor
In Go it does not exist the concept of a constructor like in other languages. A
struct is a very flexible construct that can be defined in many ways. When
working with structs it is very important to take into consideration fields zero
values and how these values may impact the code. In many cases, it is a good
practice to define constructors, especially when certain values are not valid.
JavaEE/WildFly/vscode. Debugging a web application in the vscode in conjunction with the WildFly server
As an experiment, I tried to debug a simple web application running on the WildFly server in vscode.
Of course, vscode does not have the same completeness as IntelliJ IDEA in terms of features,
but it can be considered as a kind of alternative.
So, in order to debug your application, start the WildFly server in debug mode,
specifying the port to which vscode will connect (in my case, port 8787 is specified):
standalone.sh --debug 8787
After that add the configuration:
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug (Attach)",
"projectName": "your_project_name",
"request": "attach",
"hostName": "your_host_name",
"port": "debugging_port"
}
]
}
In my case the configuration looks like this:
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug (Attach)",
"projectName": "webapp",
"request": "attach",
"hostName": "localhost",
"port": 8787
}
]
}
Next, start debugging by pressing F5
Now everything is ready, so you can set breakpoints and debug your application.
Happy debugging 🖖
Ruby. Iterating through a collection within specified a window
Rust has a method - windows (or equivalent - chunks)
fn main() {
let ints = [0, 1, 2, 3, 4, 5, 6, 7, 8];
let slice = &ints;
for el in slice.windows(3) {
println!("window {:?}", el)
}
}
that allows you to iterate through a slice and read elements within specified a window.
Below is the implementation of similar functionality in Ruby:
module Enumerable
def windows(n)
raise ArgumentError.new("Expected a value greater than 0") if n <= 0
return to_enum(:windows, n) unless block_given?
return nil if self.size == 0
(0..(self.size/n)).each do |i|
l = i * n
yield self[l...(l + n)]
end
end
alias_method :chunks, :windows
end
irb(main):014:0> [0, 1, 2, 3, 4, 5, 6, 7, 8].windows(3).each { |el| puts el.join(',') }
0,1,2
3,4,5
6,7,8
irb(main):015:0> [0, 1, 2, 3, 4, 5, 6, 7, 8].windows(0).each { |el| puts el.join(',') }
(irb):3:in `windows': Expected a value greater than 0 (ArgumentError)
irb(main):016:0> windows = [0, 1, 2, 3, 4, 5, 6, 7, 8].windows(5)
=> #
irb(main):017:0> windows.each { |el| puts el.join(',') }
0,1,2,3,4
5,6,7,8
Why algorithms (in particular, I/O algorithms) are important
Suppose we have a two-dimensional array, which is a map with given heights at different points. Let's calculate the average elevation.
To do this, you can go through either each row:
sum = 0 for i = 0 to m - 1 do for j = 0 to m - 1 do sum = sum + A[i, j] avg = sum / m^2or each column:
sum = 0 for j = 0 to m - 1 do for i = 0 to m - 1 do sum = sum + A[i, j] avg = sum / m^2Then summarize all heights and divide by the number of points on the map. Do you think there is any difference between these methods? It would seem not, but in fact, there is. The first method (traversing all rows) turns out to be more productive than the second method (traversing the columns). The whole thing is related to the organization of the array in memory and access to each cell. I tried to compare on Java. That's what I did.
// Computing the average elevation
class Avg {
public static void main(String[] argv) {
int n = 1000; // 1000 * 1000 = 10^6
int[][] matrix = new int[n][n];
fillMatrix(matrix, n, 1);
long start = System.nanoTime();
int avg = avgRowByRow(matrix);
System.out.println(String.format(
"avg (Row By Row) = %s,
it takes %s nano-seconds",
avg,
System.nanoTime() - start
));
start = System.nanoTime();
avg = avgColumnByColumn(matrix);
System.out.println(String.format(
"avg (Column By Column) = %s
it takes %s nano-seconds",
avg,
System.nanoTime() - start
));
}
private static void fillMatrix(int[][] matrix, int n, int default_value) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = default_value;
}
}
}
private static int avgRowByRow(int[][] matrix) {
int sum = 0, m = matrix.length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
sum = sum + matrix[i][j];
}
}
return sum / m / m; // sum / (m * m)
}
private static int avgColumnByColumn(int[][] matrix) {
int sum = 0, m = matrix.length;
for (int j = 0; j < m; j++) {
for (int i = 0; i < m; i++) {
sum = sum + matrix[i][j];
}
}
return sum / m / m; // sum / (m * m)
}
}
Then I tried to run it a couple of times and got the following result.
The result can be said to be obvious:
avg (Row By Row) = 1, it takes 3822568 nano-seconds avg (Column By Column) = 1, it takes 5646746 nano-seconds avg (Row By Row) = 1, it takes 3902352 nano-seconds avg (Column By Column) = 1, it takes 5467638 nano-seconds avg (Row By Row) = 1, it takes 3939734 nano-seconds avg (Column By Column) = 1, it takes 5077092 nano-seconds avg (Row By Row) = 1, it takes 3736544 nano-seconds avg (Column By Column) = 1, it takes 4950847 nano-seconds avg (Row By Row) = 1, it takes 3900019 nano-seconds avg (Column By Column) = 1, it takes 5009578 nano-seconds avg (Row By Row) = 1, it takes 3954720 nano-seconds avg (Column By Column) = 1, it takes 5109380 nano-seconds avg (Row By Row) = 1, it takes 3824056 nano-seconds avg (Column By Column) = 1, it takes 5276105 nano-seconds
API Documentation. Multiple examples in Swagger
When describing the API documentation, sometimes there is a need to add several examples of responses.
This is necessary for the possibility of a more complete description of the API documentation,
since this API documentation is a kind of contract between the backend and the frontend.
If you still use Swagger v.2.0 then you face the limitation - adding multiple examples is not supported.
To get around this limitation, you need to go to the OpenAPI v. 3.0.0 specification.
Then you will be able to add examples as follows.
- One example:
The differences between Swagger v.2.0 and the OpenAPI v. 3.0.0 specification are generally not so big:
- One example:
responses:
"200":
description: user creation successful
content:
application/json:
example:
token: fEt4IouUyRrqlx80treEWwq8
- A few examples:
responses:
"422":
description: user creation failed
content:
application/json:
schema:
properties:
response:
$ref: "#/components/schemas/ErrorResponse"
examples:
"Missing parameters":
value:
error: 'error-1'
message: 'error-message-1'
"Validation failed":
value:
error: 'error-2'
message: 'error-message-2'
The differences between Swagger v.2.0 and the OpenAPI v. 3.0.0 specification are generally not so big:
Swagger v.2.0 | OpenAPI v.3.0.0 ----------------------|------------------- info | info ----------------------|------------------- host | basePath | servers schemes | ----------------------|------------------- security | security ----------------------|------------------- paths | paths ----------------------|------------------- externalDocs | externalDocs ----------------------|------------------- tags | tags ----------------------|------------------- | securityDefinitions | | components: ----------------------| parameters produces | responses ----------------------| examples consumes | requestBodies ----------------------| headers definitions | links parameters | callbacks responses | securitySchemes |So the transition itself should not be difficult.
Subscribe to:
Posts
(
Atom
)