Search This Blog

28 July 2025

KISS is popular, lets make this popular as well


Cats Dancing Salsa Slowly Eating Fires


Complicated, Difficult and Slow

versus

Simple, Easy and Fast


Complicated

a

t

s


Difficult

a

n

c

i

n

g


Slow

a

l

s

a


Simple

l

o

w

l

y


Easy

a

t

i

n

g


Fast

r

i

e

s

13 March 2024

Flutter


Let's look at some data for Flutter usage taken from the StackOverflow yearly developer survey. We will track how much Flutter and Dart change over the years. We can see that up to 2021 Flutter is growing for a top of 13.55%. After 2021 there is a downward trend.










https://survey.stackoverflow.co/2019

https://survey.stackoverflow.co/2020

https://survey.stackoverflow.co/2021

https://survey.stackoverflow.co/2022

https://survey.stackoverflow.co/2023/

https://survey.stackoverflow.co/2024/

https://adevs.com/blog/react-native-vs-flutter/#:~:text=Flutter%20holds%20~46%25%20cross%2D,vs%20RN%208.43%25%20overall%20usage.

Some other ratings. These don't rank frameworks, but knowing the connection between Flutter and Dart, we would look at Dart ratings:

https://redmonk.com/sogrady/2023/05/16/language-rankings-1-23/

Rates Dart at place 19.

https://www.tiobe.com/tiobe-index/

Rates Dart at place 32 with overall percentage of 0.50%.

It seems that Flutter is following the normal path for a cross platform framework. Initial growth, because a lot of people believe the promise of write once, run everywhere, faster, better, easier. Then cool off, because these promises are not quite correct in general.

Comparing cross platform development for mobile, I can say Flutter looks best at the moment. Seems a lot easier than for example React Native. In addition it can do web applications as well.

Apart from Cordova or any embedded browser view framework, any of the other frameworks bring a big build complexity with them - what is the build process; what framework specific libraries are you going to use; how does this new dependencies tie with your project; what if you need to have a part of the application in native, how does this tie with the framework; Unknowns, decisions, problems and dilemmas. With native you have one problem - supporting two platforms - having two developer profiles Android and iOS. With cross platform you have additional problems.

In general if web is enough, than this is your develop once, run everywhere solution - but still as with the cross platform frameworks's promises for "write once, run everywhere, faster, better, easier", this isn't quite true - supporting different browsers, browsers on different OS, different screen sizes (desktop, mobile), etc. Otherwise if you need some cross platform keep native with embedded browser view.




08 July 2022

WebRTC Android application

Small Android application for video and audio communication with WebRTC with a WebView.

The repository at Github:

 https://github.com/ektodorov/WebRtcWebView

31 July 2019

Convert video files

If you have a home video security system - DVR, NVR, it is possible that it outputs files in a dav file format. Which is quite inconvenient, although most manufacturers of such systems would supply a video player either on disk with the equipment or you would have to fish for it in their website. Oh and one big "but", but this player is for Windows only. The same goes if you look online there are one or two players only for Windows.
What else can you do.
FFmpeg ofcourse.
One simple command:

ffmpeg -y -i movie.dav movie.mp4 

will turn your dav file into mp4 file, which you can play on any player.
But what if you don't want to know what is ffmpeg, don't want to download and install it, don't want to learn how to use it ?

There is an app for it :D

Yes there are applications for Android which use ffmpeg and provide you a convenient interface for it - well some not so convenient because they would just expect you to provide them with the command you want ffmpeg to run, but others will have a GUI which will let you select your options and they will do the rest.
So in the Google Play Store search for ffmpeg and try some of the applications that will come up as a result.

Here is an application that does only that and some more because it will convert any video format to mp4 not only dav:

 


01 May 2018

Native vs Progressive Web Application (PWA)

I recently watched a video comparing Native vs Progressive Web applications. It was about how a PWA can look and behave as much as possible as a Native app. There was a part something like - look here the browser address bar isn’t even visible and look we can add a shortcut to this page on the Home screen. Great so we are deceiving the user and it is not clear he is in the browser by hiding the address bar. So we are fragmenting the places we can have bookmarks to pages in the browser and on the Home screen - yes it is convenient to have an option in the browser to be able to place a bookmark to a page on the Home screen, but it is an option and the user should make a concise decision if it is something that he uses that much that he needs it on the Home screen, not some norm for all web applications. My point is if it is no obscure that we are using a web application that is running in the browser, the next things is users searching for an update at the App Store for this application, because they have forgotten that it is a site they are visiting with the web browser. And yes a big one is - if it is a web application it is write once run everywhere. Well yes, if you have written it with support for every browser that is. Users can run any number of browsers on their devices and if it is going to be “run everywhere”, then you need to build support for all the browsers. At least if it is native application with web content
it has to support only the Native WebView components for the systems. There is nothing bad about having a web application instead of Native application, there are pros and cons, but be proud of the good things about having a web application and be proud it is running in the web browser.

23 April 2018

Android Socket connections

Here we have an Android application that can act as a socket client, server or both for Peer-to-Peer connectivity. It is a kind of continuation to a previous blog post: https://techzealous.blogspot.bg/2018/04/peer-to-peer-connection-with-java-p2p_18.html
It can provide you with a convenient way to test connectivity between peers in a network without the need to create your own project if you only need a quick working example.
At the bottom part of the application we get a message log of what the application is doing or any exceptions that we get if the desired address and port combination is not available for use (it is already in use. After we close an address it is not made available by the OS for some time, so this has to be kept in mind as well).

GitHub repository of the application:
https://github.com/ektodorov/P2P_Sockets_Android

  (P2P Sockets Android application)

18 April 2018

Peer-to-Peer connection with Java (p2p)

Let us start with a bit of information on sockets.
In the case that we want to use the same port to connect and to accept incoming connections, we have to first start connecting to the remote host and then to start accepting incoming connections, because we can't bind to a Socket if it is already listening for connections, which is the case when we start accepting, and after that we won't be able to bind to the same port when we try to connect. Although on some systems it would be possible, it all depends on the sockets implementation in the OS.
As we can read in the Socket man page - http://www.skrenta.com/rt/man/socket.4.html :
"
SO_REUSEADDR
              Indicates   that   the  rules  used  in  validating
              addresses supplied in a bind(2) call  should  allow
              reuse  of local addresses. For PF_INET sockets this
              means that a socket may bind, except when there  is
              an  active  listening  socket bound to the address.
              When the listening socket is  bound  to  INADDR_ANY
              with  a  specific  port  then it is not possible to
              bind to this port for any local address.
"
More on this topic:

https://stackoverflow.com/questions/14388706/socket-options-so-
reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t/14388707#14388707

Now for the connections.

Connect:
We need to bind only using a port. When connecting the local address is usually "address any", that is why we only supply a port number. We are connecting to the public IP of the other machine (IP that is visible from the Internet) and we supply the IP address and the port number.

Socket socket = new Socket();
socket.setReuseAddress(true);
InetSocketAddress inetSocketAddress = new InetSocketAddress(44445);
socket.bind(inetSocketAddress);
InetSocketAddress socketAddress = new InetSocketAddress("11.222.333.555", 44446);
socket.connect(socketAddress, 30000);

Accept:
When accepting a connection we need to bind to the local IP address. If for some reason we don't get the actual local IP addres from getLocalHost (the OS may not allow us to have access to it and instead we either get the "address any" 0.0.0.0 or the loopback 127.0.0.1) we have to supply it ourselves:
InetAddress localAddress = InetAddress.getByName("192.168.100.10");

ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
InetAddress localAddress = InetAddress.getLocalHost();
InetSocketAddress socketAddress = new InetSocketAddress(localAddress, 44446);
serverSocket.bind(socketAddress);
Socket socket = serverSocket.accept();

If the clients are in the same LAN network or neither of them are behind a Firewall or a NAT, we can have one of them only accept incoming connection and the other one only connect and they will establish a connection. But if one or both of them are behind a Firewall / NAT we would have both of them connect and accept so that they punch holes in their Firewall / NAT so that the incoming connection can go through.
We have to remember that Peer-to-Peer connection is not guaranteed to succeed, because the hole punching may not be possible depending on the network setup that our hosts are in, either by accident or the network may have been setup by intention to prevent such connections on purpose. In that case we can have a relayed Peer-to-Peer communication between the two hosts - both connect to a server on the Internet and it relays the data between them. More on Peer-to-Peer communications over the Internet - http://www.brynosaurus.com/pub/net/p2pnat/

Connect and Accept part as Java methods and how to call them:

accepting("111.222.333.444", 44446);
connecting(44445, "111.222.333.555", 44446);
Of course each of these methods has to be called on a separate thread.


1:  public void accepting(String aHostLocal, int aPortLocal) {  
2:          System.out.println("accepting");  
3:          ServerSocket serverSocket = null;  
4:          OutputStream outputStream = null;  
5:          BufferedReader bufferedReader = null;  
6:          try {  
7:              serverSocket = new ServerSocket();  
8:              serverSocket.setReuseAddress(true);  
9:          
10:        System.out.println("accepting, bind to=" + aHostLocal);  
11:        InetSocketAddress socketAddress = new InetSocketAddress(aHostLocal, aPortLocal);  
12:        serverSocket.bind(socketAddress);  
13:          
14:        System.out.println("accepting, accept");  
15:        Socket socket = serverSocket.accept();  
16:          
17:        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
18:        int character = bufferedReader.read();  
19:        System.out.println("accepting, read character=" + character);  
20:        outputStream = socket.getOutputStream();  
21:        outputStream.write(character);  
22:        outputStream.flush();  
23:      } catch (IOException e) {  
24:        e.printStackTrace();  
25:      } finally {  
26:          if(bufferedReader != null) {  
27:              try {  
28:                      bufferedReader.close();  
29:                  } catch (IOException e) {  
30:                      e.printStackTrace();  
31:                  }  
32:          }  
33:          if(outputStream != null) {  
34:              try {  
35:                      outputStream.close();  
36:                  } catch (IOException e) {  
37:                      e.printStackTrace();  
38:                  }  
39:          }  
40:          if(serverSocket != null) {  
41:              try {  
42:                      serverSocket.close();  
43:                  } catch (IOException e) {  
44:                      e.printStackTrace();  
45:                  }  
46:          }  
47:      }  
48:          System.out.println("accepting, end");  
49:      }  
50:        
51:      public void connecting(int aPortLocal, String aHostRemote, int aPortRemote) {  
52:          System.out.println("connecting");  
53:          Socket socket = null;  
54:          OutputStream outputStream = null;  
55:          BufferedReader bufferedReader = null;  
56:          try {              
57:              socket = new Socket();  
58:              socket.setReuseAddress(true);  
59:          
60:              if(aPortLocal > 0) {  
61:                  InetSocketAddress inetSocketAddress = new InetSocketAddress(aPortLocal);  
62:                  System.out.println("connecting, bind to=" + inetSocketAddress);  
63:                  socket.bind(inetSocketAddress);  
64:              }  
65:          
66:              System.out.println("connecting, mHostRemote=" + aHostRemote);  
67:              InetSocketAddress socketAddress = new InetSocketAddress(aHostRemote, aPortRemote);   
68:        System.out.println("connecting, connect");  
69:        socket.connect(socketAddress, 30000);  
70:          
71:        System.out.println("connecting, sending 10");  
72:        outputStream = socket.getOutputStream();  
73:        outputStream.write(10);  
74:        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
75:        int character = bufferedReader.read();  
76:        System.out.println("connecting received character=" + character);  
77:        outputStream.flush();  
78:      } catch (IOException e) {  
79:        e.printStackTrace();  
80:      } finally {  
81:          if(bufferedReader != null) {  
82:              try {  
83:                      bufferedReader.close();  
84:                  } catch (IOException e) {  
85:                      e.printStackTrace();  
86:                  }  
87:          }  
88:          if(outputStream != null) {  
89:              try {  
90:                      outputStream.close();  
91:                  } catch (IOException e) {  
92:                      e.printStackTrace();  
93:                  }  
94:          }  
95:          if(socket != null) {  
96:              try {  
97:                      socket.close();  
98:                  } catch (IOException e) {  
99:                      e.printStackTrace();  
100:                  }  
101:          }  
102:      }  
103:          System.out.println("connecting, end");  
104:      }  

31 March 2018

Sentinel image capture software

I have updated the Sentinel project. It now has a Desktop application as well. You can checkout the project at GitHub:


Now you can directly download an application without the need to build the project yourself. There is a Downloads directory that has an Android application and a Desktop application for Windows, Mac OS and Linux.
As you can read in the readme of the project repository, for the Eclipse project we are not using Maven, because one of the libraries has issues resolving from Maven and instead of having some of them with Maven and that one not, we decided to go for manual dependency resolution for all of them.

(Sentinel for desktop)

The images or videos will be recorded in the current working directory of the application.

27 February 2018

Page security


Some time ago I noticed a problem with the security on some of the pages of a bank.
If we visit this address https://www.<blurred :)>.bg/bg/debitni-karti/page/10 , we see the result on image1 - green padlock and green text in the address bar of the browser, which informs us that the communication with this page is secured with an Extended Validation SSL certificate.

(image1)

If we continue browsing to the site and go to the pages for card products,  for example: https://www.<blurred :)>.bg/bg/page/3301#nasheto-predlojenie , we no longer see the green padlock and green text, but a gray padlock with a yellow triangle and exclamation mark. If we click on it we click on it it says that the connection to the page is not secure and the reason is that some of the content is not served over https - image2, image3, image4
(image2)

(image3)

 
 (image4)

If we look at the source code of the page we see that three of the images on that page are with URLs over http protocol. If we try to access these images we see that they are not available and that the server redirects us to their new location which is over https protocol. So the browser is making an unnecessary request over http just to get a response code 302 and a "Location" header with the new address of the image.
So the images have been removed from http and they are only accessible by https, but they have just forgotten to update some of the pages "src" attributes, and the browser is making an unnecessary http request.
(image5)


Needles to say I have informed the bank of their insecure pages and they have immediately solved the issue, of-course not missing to send a "Thanks" my way, which is always nice to hear.

I remember pointing out a problem with the e-commerce pages of a PC parts store, which prevented them from being loaded - the user had to manually reload the page if it was opened as a new tab. They fixed it after a week or so, but didn't even bother to say "Thank you". 

But here we see www.<blurred :)>.bg having a lightning fast reaction and this is what is expected when it comes to core business :)

17 February 2018

A * (A Star pathfinding)

    The repository contains a Java Eclipse project and Xcode iOS application project.
With the iOS application we can set the size of the maze and create it by touching on the squares to turn them from an empty walk able space into a wall square. We can set the start and end location and we can swipe on the map to scroll it in all directions if it can't fit on the screen, and we can pinch to zoom in and out in order to make the whole board visible or to make it easier to click on the board. Initially the size of the board is the number of squares that fit in the view size. We can set the number of squares we want the board to be in the "Width" and "Height" input fields and press on the "Create" button and we will get a new board with the desired number of squares.
    The Java implementation doesn't have a UI. We give it the maze in the ConstantsA class and we get the result in the console.


The start and end location are the squares with green color, the red colored squares are the walls and the yellow colored squares is the path.


Repository of the project at GitHub:

21 September 2017

Digital life

    Let’s code a little JavaScript project.
We have a world/ labyrinth / map and some creatures that roam in it. The world is described with walls and movable space. The creatures can use only the movable space to move and cannot move through the walls. The creatures have a field of vision of 1 square around them.

We will use some symbols to denote each one of the objects in our world:
    wall - *
    movable space - white space (space " ")
    creature - o

We will store the world in a two dimensional array. This way we can denote a location in the world with:
    world[x][y]

We could have used a one dimensional array. Then a location in the world would be:
    index = y * width + x
    world[index]



Here is the small repository of the project:

09 September 2017

Marvin framework on Android

    If you remember our Sentinel application, we considered using Marvin Framework for the image comparison, but it uses some Java packages that are not available on Android.
    Now we take a second look at it.
    Well it turns out that we don't want to port it, because it is using awt and that is a lot of work that we don't want to do right now.
    But here is an example of using Marvin Framework on Android. We are using the GrayScale filter. We have updated the instance variable "image" of the MarvingImage class to use a Bitmap instead of a BufferedImage:
// Image 
protected Bitmap image; 
And here is the code to apply a GrayScale filter:
1:          File fileOut = new File(getCacheDir(), "image.png");  
2:          BufferedInputStream inputStream = null;  
3:          FileOutputStream fos = null;  
4:          try {  
5:            inputStream = new BufferedInputStream(getAssets().open("ic_launcher.png"));  
6:            fos = new FileOutputStream(fileOut);  
7:            byte buffer[] = new byte[8192];  
8:            int length = 0;  
9:            while((length = inputStream.read(buffer)) > 0) {  
10:              fos.write(buffer, 0, length);  
11:            }  
12:            fos.flush();  
13:          } catch (IOException e) {  
14:            e.printStackTrace();  
15:          } finally {  
16:            if(inputStream != null) {  
17:              try {inputStream.close();} catch (IOException e) {/* do nothing */}  
18:            }  
19:            if(fos != null) {  
20:              try {fos.close();} catch (IOException e) {/* do nothing */}  
21:            }  
22:          }  
23:    
24:          String filePath = fileOut.getPath();  
25:          Log.i(TAG, "filePath=" + filePath + ", absolutePath=" + fileOut.getAbsolutePath());  
26:    
27:          //Change the ivar  
28:          // BufferedImage image  
29:          //int MarvinImage with Bitmap  
30:          Bitmap myBitmap = BitmapFactory.decodeFile(filePath);  
31:          int[] pixels = new int[myBitmap.getWidth() * myBitmap.getHeight()];  
32:          myBitmap.getPixels(pixels, 0, myBitmap.getWidth(), 0, 0, myBitmap.getWidth(), myBitmap.getHeight());  
33:          MarvinImage image = new MarvinImage(myBitmap.getWidth(), myBitmap.getHeight());  
34:          image.setIntColorArray(pixels);  
35:    
36:          GrayScale grayScale = new GrayScale();  
37:          grayScale.load();  
38:          MarvinImagePlugin imagePlugin = grayScale;  
39:          //MarvinImagePlugin imagePlugin = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.color.grayScale.jar");  
40:          imagePlugin.process(image, image);  
41:          image.update();  
42:    
43:          //implement the  
44:          // MarvinImageIO->loadImage  
45:          // MarvinImageIO->saveImage  
46:          //so that they don't rely on the javax package  
47:  //        MarvinImage image = MarvinImageIO.loadImage(filePath);  
48:  //        MarvinImagePlugin imagePlugin = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.color.grayScale.jar");  
49:  //        imagePlugin.process(image, image);  
50:  //        image.update();  
51:    
52:          int[] colorArray = image.getIntColorArray();  
53:          Bitmap bitmap = Bitmap.createBitmap(colorArray, myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.ARGB_8888);  
54:          mImageViewMain.setBackgroundDrawable(new BitmapDrawable(bitmap));  

Building the application


    When I am working with a technology, I am like - how other people think and say it is difficult, it is easy stuff.
    And when I look in to a new language or technology stack, I am like - oh I have all these tools and things, now I understand why someone would say it is difficult, because it is.
    And after a few days or weeks when I am over the hump, I am again to my old self - it is not difficult at all, I can't believe I considered it to be difficult, and how can anyone say it is.
Keep hustling.





07 August 2017

Shortcut application


    You have a nice website or web application that is responsive and all, but you also want presence on the Google app store. There are solutions to package your nice web content or application into an Android application, but we consider this would put you into a disadvantage. You either build a native application or just direct users to your web application that is build to run in the browser, that is were its strength is. But still you want present on the store. Well then just create an application that will redirect users to your web application in the browser of the device.
    Here is an example in the link. You could modify it by changing the icons, the application name and the URL it opens in the browser and you are good to build and upload to the store:

30 April 2017

EndorRouting - pathfinding between planets in a solar system

I came across this interesting challenge
https://www.questers.com/news/quest-wars-II-new-frontiers 

It seems more of a Math Wars than Star Wars, than their previous one (solution for the Quest Wars I challenge - Store Locations), but here goes nothing :)

Solution

GitHub repository:
https://github.com/ektodorov/EndorRouting
there you can find the source code for the Android application, as an Android Studio project.

As we have a solar system, we are using a polar coordinate system.
We can find the implementation of the routing algorithm in
ConstantsE.java source file, method: getRouteMinimax

In the same source file we can also find other implementations of routing calculations, but as we have commented in the source, they are either not optimal; a lot less correct or both.

Of course the shortest path between two planets would be a straight line. In "figure 1" we see this route, but while we are traveling in our space ship, the planet keeps traveling on its orbit as well and by the time we reach the planet we see that it has moved and is no longer where we made our route - "figure 2".
We can constantly keep updating our route while we travel - "figure 3". But this means a bit longer path. Instead we calculate where would the planet be at the time that it takes us to cover the route and make our route to that location - "figure 4". We are calculating it to 1 kilometer, but we can calculate it to as much or as little as we need it.

 figure 1

figure 2

figure 3

figure 4




We have lavishly used floats and doubles, but if we want to speed things up we have to consider where we can sacrifice on precision and use integers instead.
The Minimax calculations are performed on a single thread and as we know most of the star citizens use multi-core mobile devices that have at least 2 or 4 cores and the marketing people sent on new market planets are bound to have the newest and flashiest CPUs with more than 8 cores, so updating that part of the calculations to take advantage of multi-threading would bring a big benefit.

Please do not install the software on your space ships yet, because it is not production ready. It has small pieces missing like validation of input and such. It is just a prototype.

 (Planets)


 (Solar system -
The movement is updated only 4 times a second. If we want it to be smoother, we just need to update it more times per second)


01 February 2017

Complicated, by design

Or as I say why should it be simple, easy and fast when it can be complicated, difficult and slow.

    'Simple, readable easy to maintain implementation.'
    'Complicated, hard to read and follow, difficult to maintain implementation.'
    It is not hard to say which one of both is better and preferred. But there is something that constrains and partially drives the implementation and that is the design.
-if we have simple system design it is easy to have the first kind of implementation.
-if we have somewhat complicated design it is less simple to have the first kind of implementation, but it is still possible.
-if we have an overly and unnecessarily complicated design, then it is almost impossible to have the first kind of design, no matter how much good practice, knowledge and implementation mastery we throw at it.
Don’t forget, design comes first.

03 January 2017

Detect object movement

    Here is our small surveillance camera software. The application uses the camera of the device. The user positions the device to a position and does not have to look all of the time if an event in the camera view happens, when something in the image changes (there is activity on the field that the camera is observing it draws a rectangle on the screen where something has changed or is changing and plays a sound). 
    - feature to select what source to use - Camera; Video file; Sequence of images.
    - feature to not show movements due to camera movement - image stabilization.
    - feature to play a sound when there is a difference detected

    The libraries that we considered for this projects are listed below. Initially we wanted to use Marvin framework, but it uses Java packages that are not available in Android and porting the framework to Android would be a project of its own. That is why our next choice was Catalano Framework which can be used in an Android application without any modifications.

Marvin Image Processing Framework

Processing

JMagick - Java wrapper for ImageMagick API

Catalano Framework

OpenCV - (Open Computer Vision)

    For the image stabilization feature we considered using Phase correlation or Convolution, and decided to use a filter we are already using which is provided by the Catalano Framework - Catalano.Imaging.Filters.Difference.
We thought that it was using Convolution to calculate the difference, but after looking at the source it turns out it is not. If it was using convolution matrix it would probably have had better results in finding differences.
Instead of performing the image stabilization using the whole size of the image we use a subset of the image. We get part of the image and another slightly bigger part of the image and calculate differences with increasing offsets to find the smallest difference and calculate the offset point from it.
Would we have used Phase correlation, we would have done the same with different delays to find where the frequencies match the most.
When there is a movement in different parts of the screen - probably different objects, the whole area will be reported and not individual objects, because we decided that it is not so important to split the areas. To add this functionality, we have to just calculate changes and group them to different clusters, so that we can separate different objects in movement on the screen.
 
Repository of the project at GitHub:
https://github.com/ektodorov/sentinel

13 December 2016

Keeping it localized

    We thought of implementing a small web app in Go for localization of resources and translations. There are such apps available:

    But then we thought it is not that important tool. The job can be accomplished in a shared spreadsheet. Like our example of issue tracking:

    The same can be done when we want to localize our resources or translate a text in multiple languages. One spreadsheet per language and we are done. No need for special tools, when everyone already is familiar and used to using the tool, in this case a spreadsheet editing program.

06 December 2016

Automation, Not ?

    We all know that automation is good. No one likes boring repetitive task that can be passed to a machine to execute. But if we specifically and regularly are forced to change our code just to accommodate automation, well then "you are doing it wrong". Yes there are decisions that we need to make so that automation is possible, but it is possible through clean, well structured and maintainable code. That is it. (here is an article with the same opinion and some more things: http://ithare.com/testing-my-personal-take-on-testing-including-unit-testing-and-atddbdd/).
Automation should bend backwards, sideways and any other way to fit our workflow, not the other way around. Otherwise we are in the case of those memes, which mock "doing automation the manual way".

13 November 2016

Postman

    We were reminded to mention a great tool - Postman, because of this “New from Postman” issue:


    I don’t remember since when I started receiving these Postman newsletters, but they are great, Postman is great. And I am sure we would all be very surprised that there are a lot of people developing services or applications that consume services, that don’t use such tools. It may not be Postman, there are other solutions, but please do use something.