This is the first article in the series “Devel­oping our programming language in Java” which is aimed to show the full path of creating a language, as well as writing and maintaining tools for it. By the end of this article, we will implement an inter­preter with which it will be possible to execute programs in our language. Any programming language has a syntax that needs to be converted into a data structure that is conve­nient for validation, trans­for­mation and execution. As a rule, such a data structure is an abstract syntax tree (AST). Each tree node repre­sents a construct that occurs in the source code. The source code is parsed by the parser, and the output is AST.

Languages have been developed for a long time, and therefore at the moment we have quite a few mature tools, including parser gener­ators. Parser gener­ators take a description of the grammar of a particular language as input, and as output we get parsers, inter­preters and compilers.

In this article, we will consider the ANTLR tool. ANTLR is a utility that receives a grammar in the form EBNF as input, and interfaces/classes as output (in our case, this is java code) for parsing programs. The list of languages in which parsers are generated can be found here.

Grammar example

Before moving on to real grammar, let’s try to describe some of the rules of a typical programming language in words:

  • VARIABLE is an IDENTIFIER
  • DIGIT is one of the characters 0 1 2 3 4 5 6 7 8 9
  • NUMBER is one or more elements of type DIGIT
  • EXPRESSION is NUMBER
  • EXPRESSION is VARIABLE
  • EXPRESSION is EXPRESSION ‘+’ EXPRESSION
  • EXPRESSION is ‘(‘ EXPRESSION ’)’

As you can see from this list, a language grammar is a set of rules that can have recursive links. Each rule can refer to itself or to any other rule. ANTLR has many operators in its arsenal to describe such rules.

: marker of the beginning of the rule
; rule end marker
| alternative operator
.. range operator
~ denial
. any character
= assignment
(...) sub-rule
(...)* repeating of a subrule 0 or more times
(...)+  repeating of a subrule 1 or more times
(...)? subrule, may be missing
{...} semantic actions (in the language used as the output - for example, Java)
[...] rule parameters

ANTLR rule examples

The following example describes the rules for integers and floating-point numbers:

NUMBER : [0-9]+ ;
FLOAT : NUMBER '.' NUMBER ;

It is very important to under­stand that the grammar describes only the syntax of the language on the basis of which the parser will be generated. The parser will generate an AST, with which help it will be possible to implement the semantics of the language. In the previous example, we set a rule for parsing an integer, but did not describe how much memory the number occupies (8 bits, 16, …), and whether the number is signed or unsigned. For example, in some programming languages you can start using a variable without declaring it. You can also not declare the type of the variable; in this case the type will be deter­mined automat­i­cally at runtime. All these rules of language semantics are not described in the grammar, but are imple­mented in another part of the language.

ANTLR tokens and expressions

ANTLR grammar consists of two types of rules: tokens and expres­sions, which are used to define the structure of the grammar and parse input.

Tokens are rules that define individual lexical elements of the input language, such as numbers, identi­fiers, operation signs, and so on. Each token corre­sponds to a certain type of token, which is used for further processing by the parser. The lexical analyzer scans the input text, parses it into tokens, and creates a sequence of tokens, which are then passed to the parser. They are written in uppercase (For example: NUMBERIDENTIFIER).

Expres­sions are rules that define the grammar structure of the input language. They describe how tokens are related and how they can be combined into more complex struc­tures. Expres­sions can contain refer­ences to tokens as well as to other expres­sions. Written in camelCase notation (For example: expressionfunctionDefinition).

Thus, the difference between tokens and expres­sions in ANTLR is that tokens define individual lexical elements of the input language and convert them into tokens, while expres­sions define the structure of the grammar and describe how tokens are related to each other in more complex structures.

Language Require­ments

Before you start imple­menting a language, you need to determine the set of features it should support. For our task, for educa­tional purposes, we will use a simple grammar. The language will support the following constructs:

  • Variables (types StringLongDouble);
  • Assignment operator (=);
  • Arith­metic operations (+, -, *, /);
  • Comparison operators (>, <, >=, <=, ==, !=);
  • Condi­tional state­ments (if , else);
  • Functions;
  • Print to the console (built-in println operator).

Grammar

And finally, a complete description of the grammar for the language:

grammar Jimple ;

// root rule of grammar
program: (statement)* EOF;

// list of possible statements
statement: variableDeclaration
         | assignment
         | functionDefinition
         | functionCall
         | println
         | return
         | ifStatement
         | blockStatement
         ;

// list of possible expressions
expression: '(' expression ')'                                      #parenthesisExpr
          | left=expression op=(ASTERISK | SLASH) right=expression  #mulDivExpr
          | left=expression op=(PLUS | MINUS) right=expression      #plusMinusExpr
          | left=expression compOperator right=expression           #compExpr
          | IDENTIFIER                                              #idExp
          | NUMBER                                                  #numExpr
          | DOUBLE_NUMBER                                           #doubleExpr
          | STRING_LITERAL                                          #stringExpr
          | functionCall                                            #funcCallExpr
          ;

// descriptions of individual expressions and statements
variableDeclaration: 'var' IDENTIFIER '=' expression ;

assignment: IDENTIFIER '=' expression ;

compOperator: op=(LESS | LESS_OR_EQUAL | EQUAL | NOT_EQUAL | GREATER | GREATER_OR_EQUAL) ;

println: 'println' expression ;

return: 'return' expression ;

blockStatement: '{' (statement)* '}' ;

functionCall: IDENTIFIER '(' (expression (',' expression)*)? ')' ;

functionDefinition: 'fun' name=IDENTIFIER '(' (IDENTIFIER (',' IDENTIFIER)*)? ')' '{' (statement)* '}' ;

ifStatement: 'if' '(' expression ')' statement  elseStatement? ;

elseStatement: 'else' statement ;

// list of tokens
IDENTIFIER          : [a-zA-Z_] [a-zA-Z_0-9]* ;
NUMBER              : [0-9]+ ;
DOUBLE_NUMBER       : NUMBER '.' NUMBER ;
STRING_LITERAL      : '"' (~["])* '"' ;

ASTERISK            : '*' ;
SLASH               : '/' ;
PLUS                : '+' ;
MINUS               : '-' ;

ASSIGN              : '=' ;
EQUAL               : '==' ;
NOT_EQUAL           : '!=' ;
LESS                : '<' ;
LESS_OR_EQUAL       : '<=' ;
GREATER             : '>' ;
GREATER_OR_EQUAL    : '>=' ;

SPACE               : [ \r\n\t]+ -> skip;
LINE_COMMENT        : '//' ~[\n\r]* -> skip;


As you have probably already guessed, our language is called Jimple (derived from Jvm simple). It’s probably worth explaining some points that may not be obvious when you first get acquainted with ANTLR.

Labels

op label has been used to describe the rules for some opera­tions. This allows us to use this label later as the name of a variable that will contain the value of the operator. Theoret­i­cally, we could avoid speci­fying labels, but in this case, we would have to write additional code to get the value of the operator from the parse tree.


compOperator: op=(LESS | LESS_OR_EQUAL | EQUAL | NOT_EQUAL | GREATER | GREATER_OR_EQUAL) ;

Named rule alternatives

In ANTLR, by defining a rule with multiple alter­na­tives, a user can assign a name to every of them, and then in the tree it will appear in a form of a separate processing node. That is very conve­nient when you need to assign to the processing of every rule option a separate method. It is important that the names must be given either to all alter­na­tives or to none of them. The following example demon­strates what it looks like:


expression: '(' expression ')'  #parenthesisExpr
          | IDENTIFIER          #idExp
          | NUMBER              #numExpr

ANTLR will generate the following code:


public interface JimpleVisitor<T> {
    T visitParenthesisExpr(ParenthesisExprContext ctx);

    T visitIdExp(IdExpContext ctx);

    T visitNumExpr(NumExprContext ctx);
}

Channels

ANTLR has such a construct as channels. Usually, channels are used to work with comments, but since in most cases we do not need to check for comments, they must be discarded with -> skip, that we have already used. However, there are cases when we need to interpret the meaning of comments or other constructs, in this case you should use pipes. ANTLR has already a built-in channel called HIDDEN that you can use, or you can also declare your own channels for specific purposes. Later, by parsing the code, you will be able to access these channels.

An example of declaring and using a channel

channels { MYLINECOMMENT }

LINE_COMMENT : '//' ~[rn]+ -> channel(MYLINECOMMENT) ;

Fragments

Along with tokens, ANTLR has such an element as fragments. Rules with a fragment prefix can only be called from other lexer rules. They are not tokens per se. In the following example, we moved the defin­i­tions of numbers for different number systems into fragments.

NUMBER: DIGITS | OCTAL_DIGITS | HEX_DIGITS;
fragment DIGITS: '1'..'9' '0'..'9'*;
fragment OCTAL_DIGITS: '0' '0'..'7'+;
fragment HEX_DIGITS: '0x' ('0'..'9' | 'a'..'f' | 'A'..'F')+;

Thus, a number in any number system (for example: “123”, “0762”, or “0xac1”) will be treated as a NUMBER token, not DIGITSOCTAL_DIGITS, or HEX_DIGITS. Jimple does not use fragments.

Tools

Before we start gener­ating the parser, we need to set up the tools to work with ANTLR. As is known, a good and conve­nient tool makes half the success. To accom­plish that, we need to download ANTLR library and to write scripts in order to run it. There are also maven/gradle/IntelliJ IDEA plugins, which we will not be using in this article, but for productive development, they can be found useful.

We need the following scripts:

antlr4.sh script

java -Xmx500M -cp ".:/usr/lib/antlr-4.12.0-complete.jar" org.antlr.v4.Tool $@

grun.sh script


java -Xmx500M -cp ".:/usr/lib/antlr-4.12.0-complete.jar" org.antlr.v4.gui.TestRig $@

Parser gener­ation

Save the grammar in the file Jimple.g4. Next, run the script like this:

antlr4.sh Jimple.g4 -package org.jimple.lang -visitor


-package option allows you to specify the java package in which the code will be generated. The -visitor option allows you to generate a JimpleVisitor interface that imple­ments the Visitor pattern.

After successful execution of the script, several files will appear in the current directory: JimpleParser.javaJimpleLexer.javaJimpleListener.javaJimpleVisitor.java. The first two files contain the generated parser and lexer code, respec­tively. The other two files contain inter­faces for working with the parse tree. In this article, we will use the JimpleVisitor interface, more specif­i­cally JimpleBaseVisitor — this one is also a generated class that imple­ments the JimpleVisitor interface and contains imple­men­ta­tions of all methods. It allows us to override only the methods we need.

Inter­preter Implementation

Finally, we have reached the most inter­esting part — the imple­men­tation of the inter­preter. Although in this article we will not analyze the issue of checking the code for errors, some inter­pre­tation errors will still be imple­mented. First of all, let’s create a JimpleInterpreter class with an eval method, which will take a string with the code for Jimple as input. Next, we need to parse the source code into tokens using JimpleLexer, then to create an AST tree using JimpleParser.

public class JimpleInterpreter {
    public Object eval(final String input) {
        // parse initial code on tokens
        final JimpleLexer lexer = new JimpleLexer(CharStreams.fromString(input));
        // create AST tree
        final JimpleParser parser = new JimpleParser(new CommonTokenStream(lexer));
        // create an object class JimpleInterpreterVisitor
        final JimpleInterpreterVisitor interpreterVisitor = new JimpleInterpreterVisitor(new JimpleContextImpl(stdout));
        // run interpreter
        return interpreterVisitor.visitProgram(parser.program());
    }
}

We have a syntax tree. Let’s add semantics with the JimpleInterpreterVisitor class we wrote, which will bypass the AST by calling up the appro­priate methods. Since the root rule of our grammar is the program rule (see program: (statement)* EOF above), the tree traversal starts from it. To accom­plish this, we call the visitProgram method imple­mented by default on the JimpleInterpreterVisitor object, to the input of which we give an object of the ProgramContext class. The ANTLR imple­men­tation consists of calling the visitChildren (RuleNode node) that traverses all the descendant items of the given tree node, calling the visit method on each of them.


// code generated by ANTLR
public class JimpleBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements JimpleVisitor<T> {
    @Override
    public T visitProgram(JimpleParser.ProgramContext ctx) {
        return visitChildren(ctx);
    }

    // other methods omitted for brevity
}

As you can see, JimpleBaseVisitor is a generic class for which you need to define the type of processing for each node. In our case, this is the Object class, since expres­sions can return values of different types. Typically, an expression must return a value, while a statement returns nothing – this is their difference. In case of statement, we can return null. However, in order not to acciden­tally encounter NullPointerException, instead of null we will return an object of type Object, which is globally defined in the JimpleInterpreter class:

public static final Object VOID = new Object();

JimpleInterpreterVisitor class extends class JimpleBaseVisitor, overriding only the methods we are inter­ested in. Let’s consider the imple­men­tation of the built-in println operator, which is described in the grammar as println: 'println' expression ;. The first thing we need to complete is to evaluate the expression, for this we need to call the visit method and pass the expression object from the current PrintlnContext into it. In the visitPrintln method, we are absolutely not inter­ested in a calcu­lation process of an expression; the corre­sponding method is respon­sible for calcu­lating each rule (context). For example, the visitStringExpr method is used to evaluate a string literal.


public class JimpleInterpreterVisitor extends JimpleBaseVisitor<Object> {
    @Override
    public Object visitPrintln(final JimpleParser.PrintlnContext ctx) {
        final Object result = visit(ctx.expression());
        System.out.println(result);
        return VOID;
    }

    @Override
    public Object visitStringExpr(final JimpleParser.StringExprContext ctx) {
        // return string literal
        return cleanStringLiteral(ctx.STRING_LITERAL().getText());
    }

    private String cleanStringLiteral(final String literal) {
        // clear string from quotation marks
        return literal.length() > 1 ? literal.substring(1, literal.length() - 1) : literal;
    }

    // other methods omitted for brevity
}

By imple­menting only these methods, the inter­preter already supports println and string literals, which allows us to execute println "Hello, Jimple!" code.

Run inter­preter

To launch the inter­preter, you need to create a standard main method, which after some small checks with the use of the JimpleInterpreter class, will run our code:

public class MainApp {
    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("usage: jimple input.jimple");
            System.exit(1);
        }

        Path path = Paths.get(args[0]);
        if (!Files.exists(path)) {
            System.err.println("File not found: " + path);
            System.exit(1);
        }

        new JimpleInterpreter().eval(path);
    }
}

Imple­men­tation details

There is no need to provide the entire imple­men­tation code of the inter­preter, a link to the source code can be found at the end of the article. However, I want to examine some inter­esting details.

As already mentioned, the inter­preter is based on the Visitor pattern, which visits the nodes of the AST tree and executes the corre­sponding instruc­tions. In the process of code execution in the current context it appears that new identi­fiers (names of variables and/or functions) need to be stored somewhere. To do this, we will write a JimpleContext class that will store not only these identi­fiers, but also the current context for executing nested code blocks and functions, since a local variable and/or function parameter must be deleted after leaving their scope.

@Override
public Object handleFunc(FunctionSignature func, List<String> parameters, List<Object> arguments, FunctionDefinitionContext ctx) {
    Map<String, Object> variables = new HashMap<>(parameters.size());
    for (int i = 0; i < parameters.size(); i++) {
        variables.put(parameters.get(i), arguments.get(i));
    }
    // create a new function scope and push it onto the stack
    context.pushCallScope(variables);

    // execution of function expressions omitted for brevity
    // remove the scope of function parameters from the stack
    context.popCallScope();

    return functionResult;
}


In our language, a variable stores a value of a type that is deter­mined at runtime. Further, in the following instruc­tions, this type may change. Thus, we got a dynam­i­cally typed language. However, some checking of types is still present in cases where performing the operation is pointless. For example, a number cannot be divided by a string.

Why do we need two passes?

The original version of the inter­preter was to implement a method for each rule. For example, if a function decla­ration processing method finds a function with the same name (and number of parameters) in the current context, then an exception is thrown, otherwise the function is added to the current context. The function call method works the same way. If the function is not found, then an exception is thrown, otherwise the function is called. This approach works, but it does not allow you to call the function before it is defined. For example, the following code will not work:

var result = 9 + 10

println "Result is " + add(result, 34)

fun add(a, b) {
    return a + b
}

In this case, we have two approaches. The first one is to require functions to be defined before they are used (not very conve­nient for users of the language). The second approach is to perform two passes. The first pass is needed for finding out all the functions that have been defined in the code. And the second is directly for executing the code. In my imple­men­tation, I chose the second approach. The imple­men­tation of the visitFunctionDefinition method should be moved to a separate class that extends the generated class JimpleBaseVisitor<T> that is already known to us.


// class finds all functions in the code and registers them in the context
public class FunctionDefinitionVisitor extends JimpleBaseVisitor<Object> {
    private JimpleContext context;
    private FunctionCallHandler handler;

    public FunctionDefinitionVisitor(JimpleContext context, FunctionCallHandler handler) {
        this.context = context;
        this.handler = handler;
    }

    @Override
    public Object visitFunctionDefinition(JimpleParser.FunctionDefinitionContext ctx) {
        String name = ctx.name.getText();
        List<String> parameters = ctx.IDENTIFIER().stream().skip(1).map(ParseTree::getText).toList();
        var funcSig = new FunctionSignature(name, parameters.size());
        context.registerFunction(funcSig, (func, args) -> handler.handleFunc(func, parameters, args, ctx));
        return VOID;
    }
}

Now we have a class that we can use before executing the inter­preter class directly. It will fill our context with the defin­i­tions of all the functions that we will call in the inter­preter class.

What does an AST look like?

In order to visualize the AST, you need to use the grun utility (see above). To do this, run grun with the parameters Jimple program -gui (the first parameter is the name of the grammar, the second is the name of the rule). As a result, a window with the AST tree will be opened. Before executing this utility, it is important to compile the code generated by ANTLR.


 # generate a parser
antlr4.sh Jimple.g4
# compile the generated code
javac -cp ".:/usr/lib/jvm/antlr-4.12.0-complete.jar" Jimple*.java
# run grun
grun.sh Jimple program -gui
# enter code: `println "Hello, Jimple!"`
# press Ctrl+D (Linux) or Ctrl+Z (Windows)
For the Jimple code println "Hello, Jimple!", the following AST will be generated:

Summary

In this article you have got acquainted with such concepts as lexical and parser analyzers. We used the ANTLR tool to generate such analyzers. You have also learned how to write ANTLR grammar. As a result, we created a simple language, namely, developed an inter­preter for it. As a bonus, we managed to visualize the AST.

The entire source code of the inter­preter can be viewed by link.

Are there any merits connected with using SaaS based solutions? If you are planning to use software development service in your business, this review will offer five reasons why you should go for SaaS solutions. The SaaS appli­ca­tions run on servers of different SaaS users and providers and are acces­sible through browsers. Rather than purchasing an appli­cation, as a user you pay a rent’, which allows you to utilize SaaS for a certain period of time. This means you will be able to reduce the use cost overtime. 

What are SaaS Based Solutions?

SaaS i.e. software as a service refers to a mode of software distri­b­ution whereby a third-party provider often hosts apps and makes them readily available to different clients online. Software as a service is among the three prime classes of cloud computing, apace with PaaS (platform as a service) and IaaS (infra­structure as a service). Some of the examples of SaaS include GoToMeeting, Common SaaS Use-Case and Google Apps among others. Here are reasons showing why you should go for SaaS based solutions when the need arises:

5 Reasons Why You Should Go for SaaS Based Solutions 

Lower Up-front Cost

SaaS generally is subscription-based not to mention it does not carry any up-front license charges, which makes it possess a lower initial cost. The management of the IT infra­structure which runs the software is performed by the SaaS provider and therefore the charges for software and hardware mainte­nance are very low.

Easy Upgrades

Easy upgrades solution is another merit that makes SaaS a suitable alter­native over the conven­tional models of software instal­lation. With this appli­cation, the SaaS provider will help in tackling the software and hardware updates for you. The provider deploys upgrades to the hosted apps and hence removes this respon­si­bility and workload from you.

Acces­si­bility and Scalability

In order to obtain a SaaS appli­cation, an internet connection and a browser is all you require to have. These things are generally present on a wide array of gadgets and from any place globally, which makes SaaS to be easily acces­sible when compared to the conven­tional business software.

SaaS providers provide a range of subscription alter­na­tives and flexi­bility to adjust subscrip­tions when and as needed. Therefore, with SaaS based solutions, as your trade grows or when number of users that require acquiring the services increase, you can change subscrip­tions easily.

Setting up and Deploying SaaS is Quick

SaaS as an appli­cation is not only already installed in the cloud, but configured also. By SaaS being quick and easy to set up and deploy, this helps minimize typical delays which often result from lengthy conven­tional software development applications. 

It is Cost-Effective Alter­native Generally

SaaS can offer notable savings due to several factors. For instance, it can help you eliminate the upfront price of installation/purchase, and on-going costs such as upgrades and mainte­nance. Rather than spending huge amounts of cash on hardware instal­lation, SaaS based solutions can be downloaded as well as maintained easily.

Bottom Line 

Utilizing SaaS based solutions in your business can help you save both time and money. Using SaaS is therefore worthy since you will be exposed to a range of merits. Furthermore, unlike the conven­tional software development appli­ca­tions, the mainte­nance respon­si­bil­ities of SaaS solutions will not be handled by your IT department, but by the vendor themselves. 

Every software development company out there knows, that no matter how polished your internal processes are, things never go as expected. Software development is one of the most challenging and at the same time compet­itive indus­tries today.

So naturally, every major business in this field strives to improve its produc­tivity and optimize workflows to overcome most common challenges.

But what exactly are those challenges?

  1. Assem­bling requirements

Poorly defined require­ments come down to simple “Garbage in. Garbage out”. The diffi­culty in require­ments gathering almost always associated with miscom­mu­ni­cation between client and software development vendor.

Sometimes the client lacks certain technical expertise and therefore puts in front overly-optimistic expec­ta­tions. Sometimes software devel­opers cannot translate techno­logical limita­tions into business perspective. Regardless of why it happens, made-project changes in require­ments always cause delays, revisions and additional expenses.

  1. Estimation & roadmap planning

Estimation of cost and clear planning happens at the very early stages of product lifecycle. And we all know that it is impos­sible to account for every­thing. It’s always a difficult task when you have to explain to the client that some deadline needs to be extended. So it’s very important to establish maximum trans­parency between two parties and keep commu­ni­cation lines on at all times.

  1. Staying on top of the technology

This one is a clear respon­si­bility of software development company. Staying on top of tech trends and be able to accom­modate most innov­ative business requests is very important because the technology changes at a rapid pace. That is why it falls down on companies to contin­u­ously educate their employees and make sure that they as a business stay competitive.

  1. Multiple testing & QA iterations

The best companies in software development sector have realized long ago that Testing and QA should never come as an after­thought or post-production process. Various itera­tions of testing need to occur throughout the project cycle. 

And when you inves­tigate the entire system, there will be bugs found. Many times the problem needs to be isolated to let the rest of the project move on. But in some cases, it is simply impos­sible and you reach a complete roadblock that slows down the development time.

IntechCore Software Development Services

Only by employing innov­ative method­ology in managing remote teams and staying on top of trends can software development company survive in the compet­itive market. Here at IntechCore, we structure our internal workflows deliver excep­tional results, infor­mation security and increased productivity.

Every day we work towards overcoming industry’s biggest challenges and deliv­ering our customers the excep­tional-quality software. We pride ourselves on succeeding in most demanding projects through continuous monitoring of progress, cost, and delivery.

 

Nowadays, the proof of concept (POC) has become more or less a standard procedure in most software development companies. POC is used to assess the viability of a product in a real market environment, where true business needs exist. In one of our previous articles, we’ve already covered how to structure POC and what goes into it exactly.

Today we’ll go beyond simple require­ments and processes and talk about setting your business goals straight in order to deliver the POC, your customers will appreciate.

One conver­sation that is often missed, when talking about POC, is how is it actually benefit the client? So here at IntechCore, we’ve compiled a small checklist to help you stay on track and think customer-first during the proof of concept.

Identify Decision Makers

Note: decision makerS.

Very often, most companies only envision their client as a single person with whom they commu­nicate. But most businesses don’t function in such total­i­tarian regime. There are multiple people who run the company and influence the final decision:

  • Business owner
  • CTO (chief technical officer)
  • Financial manager
  • Marketing lead
  • Etc.

In order for you to deliver and present truly stellar POC, you need to think about how all these people will see it. Because if you prove that the product in mind has an incredible technical appli­cation but don’t present a clear mean of marketing it, the whole project might be in jeopardy.

Define Success & Align Expectation

Perhaps the most important aspect that is getting missed all the time. You’ve helped your client launch MVP (minimum viable product), and you gather some feedback. What comes next? You haven’t actually defined any measurable criteria of success. Here are a couple of questions you might want to ask yourself and client before even starting:

  • Why are we doing this and what are we trying to achieve?
  • Which other product on the market are we competing against?
  • With what other software can we compare the product?
  • What’s right or wrong with the way we launch MVP?
  • What’s the real value of the product?
  • Who will maintain and upkeep the product?

By asking these question, both you and the client might uncover some previ­ously obscured challenges or prospects.

Also, these questions will help you in aligning expec­ta­tions with customers and avoiding the situation where the client has unreal­istic forecast.

Know What to Do Next

After a successful completion of POC, for a software development company, the logical next step is receiving a paycheck. But it doesn’t have to be this way. Having better clarity on the next steps required by each party increases the trust between companies and strengthens their partnership.

If you do a bit of extra work and strive to go beyond simple MVP launch, then you might find yourself in a position, where you have a loyal customer base who entrust you with their future projects and will mention you as a trusted partner in the future.

 

Are you planning to hire a custom software appli­cation development company soon and searching for tricks which can help you secure a reputable firm that will assure you with top-notch solutions that suit your needs? If so, this review will aid you on how to avoid being fooled by a custom software development company. Custom software development firm is a kind of company that specializes in designing software appli­ca­tions often to a particular user or category of users within insti­tu­tions. The software designed is intended to address the various needs of the users. 

Currently, the market niche for custom software development firms is occupied with both legit and experi­enced companies and the unreliable ones. Therefore, prior to entrusting any firm with your custom software development needs, it is ideal you research carefully on the various company choices you find first. 

A good research will help differ­en­tiate between the reliable custom development firms from the fake ones. Courtesy of researching, you will also get a reputable custom development company which will promise you with top-notch and affordable solutions and extremely dependable terms of service.

How to Avoid Being Fooled by a Custom Software Development Company

First, in your attempt to avoid being fooled by a custom software development firm, it is vital you know what roles these kind of companies perform. A good company is one which will ensure you get solutions which will leave you with a unique and complex website or mobile apps which supports your marketing campaigns as well as other business objec­tives. Here are some of the issues most people experience once they outsource the services of a custom software development company, which will help you avoid being fooled if you plan to hire one soon:

1. Custom Might Simply Indicate Slightly’ Modified 

Some firms claiming to be providing custom software development solutions offer merely minor-to-major imple­men­ta­tions and modifi­ca­tions of standard services. It is vital that the firm you choose is one providing templates that are well written, easily customizable and scalable. This is important since it will help you later if you will consider making a web overhaul. 

2. Any Developer May Claim to Construct Custom Software

Provided the developer can make changes to the source code of software, they will claim to be doing custom software development. This is not right. These are only but mere modifi­ca­tions that cannot make software unique and very reliable. It is recom­mended that the custom software development company you choose is one capable of handling all major modifi­ca­tions that will make you attain unique as well as superior quality software solutions.
The company you select must make the appli­cation from scratch and without utilizing any ready-made solutions. 

The Best Way to Secure a Reputable Custom Software Appli­cation Development Company

You must make sure that if the company you liaise with will use ready-made software, you know what the software is and the purposes it will serve in your business. Make sure also you ask what impli­ca­tions for future customiz­ability and scala­bility the software which will be made for you by the firm you opt to consider will offer. 

A programming language refers to a set of instruc­tions, commands as well as other syntax utilized to construct a software program. It is a set and vocab­ulary of grammatical rules which are intended to instruct a computer to carry out some specific tasks. 

Based on fact-findings, one of the most essential skills to learn in our present-day world is to know how to write appro­pri­ately a computer program. Currently, computers are being utilized in almost every company. This is because they are exceed­ingly beneficial in matters pertaining assisting a firm to scale up accord­ingly. This makes the need to learn programming languages come handy. 

However, the market niche for programming language is filled with a wide array of language options. Therefore, it is vital you do your homework accord­ingly so that you can know the kind of programming language that will be helpful with your needs before you start learning any. Here are some of the top-notch programming languages to learn in 2019:

Which Programming Language to Learn in 2019

1: Java

Java is a programming language that is mostly utilized in large insti­tu­tions and its effec­tiveness has made it stand the taste of time. This kind of programming language is widely utilized for constructing enter­prise-scale website appli­ca­tions. One of the inordinate features related to using Java is that it is exceed­ingly stable; a factor that has contributed to majority of the large enter­prises to adopt it.

If you are hunting for a development based work at a large insti­tution, it is recom­mended you consider learning Java. 

#2: JavaScript

JavaScript which is also called the fronted programming language is commonly utilized for designing inter­active frontend appli­ca­tions. A good example of JavaScript language include, when a person clicks a button on a computer that opens up a pop-up. In case of this scenario, the logic is executed through JavaScript. 

3: Swift

Swift is a programming language which is mainly used for devel­oping iOS appli­ca­tions. It is a kind of programming language that is considered an ideal option to learn since the popularity of iOS based gadgets is increasing each and every day. For instance, iPhone has managed to occupy a huge market share and thus giving Android a stiff compe­tition. Therefore, if you desire to serve this market niche, it is advisable you consider learning Swift programming. 

4: PHP

PHP is amongst the most famous programming languages that cannot be accessed directly by a computer user. Though most people consider it a nasty language, it is very easy to learn PHP. If you desire working at an old insti­tution as a backend computer developer, it is vital you consider leaning PHP programming.

5: R

R is a programming language commonly utilized for Machine Learning and Data Analysis. It is a programming language that can provide a great framework as well as built-in libraries for devel­oping strong Machine Learning algorithms. 

R can also be used for statis­tical computing and is an appro­priate language for those people who want to work as analytics in large institutions.

Bottom Line

Since nothing comes easy, make sure you put a lot of effort by researching exten­sively in your attempt to be more knowl­edgeable and informed about the afore­men­tioned programming languages. This will help you become a pro at using them and thus benefit from what they offer in the job market.

What stages of software development should you accom­plish when taking a career in this line of profession? A software developer is an expert concerned with aspects of software development procedure, which includes researching, designing, programming as well as testing of the computer software. Though most software devel­opers develop the appli­ca­tions which enable people to accom­plish projects on a computer or other devices, there are others who are respon­sible for devel­oping the under­lying struc­tures which control networks or run the devices.

Once you success­fully complete a software development career, as a computer programmer AKA software developer, you will play a prime role in the designing, instal­lation, exper­i­menting and maintaining the software systems. The programs you build will likely assist organi­za­tions offer a better service or be more efficient. Here are the phases of software development career you should expect to accom­plish in your goal to become a pro computer programmer or software developer:

The Stages of your Software Development Career

Stage#1: Coder

A coder is typically a hobbyist. Some of the respon­si­bil­ities you will have to fulfil in this stage include learning how to utilize programming language syntax, creating small projects yourself and being a good problem solver.

Stage#2: Junior Developer

As a junior developer, you will now start partic­i­pating in the IT market as a paid expert. However, you will have to work closely with other profes­sional software devel­opers who will be guiding you on what to do.

As a junior developer you will require leaning how to break issues into small and more manageable projects. You will also start learning how to link varying systems together like linking from the server-side code to a database or client-server interaction.

Stage#3: Inter­me­diate Developer

At this stage you will already be a competent contributor and team member. As an inter­me­diate developer, you will already have learned the way of building basic systems like web appli­cation. You will however be required to know how to utilize properly profes­sional tooling and to be knowl­edgeable about basic system architecture.

Stage#4: Senior Developer

As a senior developer, you will have to make more complex systems utilizing advanced patterns and methods. In this stage you will already be having some advanced and specialized programming knowledge. 

Being a senior developer will require you to be knowl­edgeable about refac­toring, design patterns and code smells, and knowledge about archi­tec­tural paradigms such as Event Sourcing, Domain Driven design, etc.

Stage#5: Lead Developer 

At this stage your focus will be to offer high-level enlight­enment to your development team. However, your prime role as a lead developer will be to act as a link between the development team and other business-oriented sections in the organization.

Stage#6: Tech Leader

In this stage your name as an expert is already renowned in some particular locations. As a tech leader you will have a specific targeted positioning or branding as to what you accom­plish well. For instance, your targeted positioning may be a particular programming language, front-end development, web security, or a developer mentor. 

Bottom Line

In order to be a successful software developer, always make sure you are open and flexible for continuous development and learning despite the role you play in your organi­zation. Stick to this principle and be certain you will always be set for advanced growth and success. 

Partic­i­pants

web.sta – web-app, target browser is Internet Explorer 9 & 11

TextSystem – stand­alone desktop appli­cation, written in Java/Swing

Inter­me­di­ate­Layer – Client-Server app, linking web.sta and TextSystem together. 

web.sta can call TextSystem via the Inter­me­di­ate­Layer. Inter­me­di­ate­Layer creates an HTTP server for this purpose and web.sta simply sends GET or POST requests to the localhost. Inter­me­di­ate­Layer processes the request parameters and starts the TextSystem. There is no need for feedback calls, so the inter­action scheme is simple and robust enough.

Citrix

In Citrix environment we can not create several listening sockets on the same IP address and port. It is necessary either to change the port, or to change the IP address. But Citrix provides a special mechanism for circum­venting this restriction, without changing the algorithm of the program. This mechanism is called Virtual IP Loopback. The admin­is­trator simply configure necessary appli­ca­tions in the Citrix config­u­ration panel and the appli­cation that uses localhost for socket connec­tions will receive not 127.0.0.1, but an IP address in the form 127.0.0. <SID + 1>, where SID is the session ID of the Windows user.

The Problem

All this worked fine under IE9 (and with other browsers too) on Windows Server 2008 R2. And then the clients wanted something new and Windows Server 2012 R2 appeared with IE11. And the whole system stopped working. Regardless of Citrix IE11 settings, when speci­fying “localhost” it always tries to establish a connection to 127.0.0.1, but nobody listens there. After a little research, we came to the conclusion that this is a bug in IE11.

RoutingService

If the virtu­al­ization for localhost does not work out of the Citrix box for IE11, then let’s write it ourselves!

For these purposes, we decided to write a windows service, which will be the simplest web server, listen to 127.0.0.1 and redirect requests to the desired Inter­me­di­ate­Layer, based on the session number of the user. We did not find a simple solution to get the SID, but we immedi­ately found SESSIONNAME in the environment variables. In IE via ActiveX we get the environment variable, pass it as a parameter to the HTTP request. In RoutingService by the sessionname through wtsapi32.lib we get the session number. Then we redirect the HTTP request and return the response to IE.

Something went wrong

We began the testing and integration of our service. But not every­thing went as smooth as we would like.

As it turned out, the name of the session can be changed, although we did not under­stand in what condi­tions it happens. But often it happened that the session name changed, and IE11 only knows the initial value of the environment variable. And persis­tently passes this value to the RoutingService.

What is in the registry?

It is necessary to find another way to get the sessionname. We have looked for infor­mation about sessions in the registry and that’s what they found: in HKEY_CURRENT_USER \ Volatile Environment we can get a list of sessions of the current user.

If the user session is one, then every­thing is fine, we can read and use it. And if there are a lot of sessions for one user, then we need to somehow determine which session we are in. We could not come up with anything better than matching the path to the temporary files folder.

Here is an example:

In IE, we get the current path to TEMP using ActiveX Scripting.FileSystemObject.

This way we managed to get the name of our session. But that’s not all. The value of the keys under the Volatile Environment is, in fact, the SID is. That is, we can immedi­ately get the necessary IP address in JavaScript and send a request to it.

Shall we simplify it? 

Finally we can get the SID and establish a connection directly, without using RoutingService. But the solution still does not look beautiful. Studying the Internet showed that the problem exists, but the solution to this problem is not described anywhere. And the Microsoft keeps silence as well. 

We hope someone with this specific problem can benefit from our experience.

Software Quality Assurance (also abbre­viated as SQA), can be defined as a systematic process which ensures that the developed software meets and complies with the standardized quality speci­fi­ca­tions. It keenly checks the adherence to the software product standards, proce­dures and processes all throughout the software development life cycle and also the test cycle. The evalu­ation is done through product evalu­ation, process monitoring, project management, and more. Read more

With every­thing going digital a Document Management Systems, also known as DMS, ensures that you are able to easily edit, manage and organize your documents. Moreover, you can also keep records and track any changes made to documents. In this post, we will focus on different compo­nents of DMS in order to under­stand its wide scope. This will give you an idea about various services offered by companies devel­oping DMS systems, Intechcore being one of them. Read more