Ways of creating multi-threaded applications in .NET (Part 2). ThreadPool Class

In Part 1 of this article, we talked about what threads are in .NET. Now, we want to dwell on the methods of background and asynchronous execution of threads in .NET apps.

These methods have advantages and disadvantages. They are not always convenient to use, but generally, background and asynchronous execution of threads offers wide opportunities in executing separate background threads for both small and long tasks.

Thread pool and its difference from the Thread class

Creation and destruction of threads are very resource-intensive processes. Performing them too often is not recommended. However, there are various small tasks that require asynchronous execution or with maximum utilization of all CPU cores. For such tasks, it is best to create a set of threads in advance and then distribute the tasks among these threads.

It would be quite good if the threads that had already completed their tasks could be re-used without wasting computational resources destroying them and creating new threads. It would also be nice if the program itself determines how many threads it would require to efficiently solve a problem.

Such a set of threads in .NET exists and is called a thread pool. It is implemented in the ThreadPool static class of the System. Threading namespace. You need not create a ThreadPool class object, and it will not work either. Such an object is created automatically when the application starts – provided the System. Threading namespace is connected in it.

If you’re interested in more, read Microsoft Roslyn – using the compiler as a service

ThreadPool can automatically increase or reduce the number of active threads to maximize task execution efficiency. The maximum allowed number of processing threads in a pool is 1023. The pool allocates a maximum of 1000 threads in an I/O operation.

To get maximum number of threads, you can use the GetMaxThreads method of the ThreadPool static class. The first parameter passed to this method returns the number of processing threads. The second parameter returns the number of I/O threads.

int nWorkers; // number of processing threads
int nCompletions; // number of I/O threads
ThreadPool.GetMaxThreads(out nWorkers, out nCompletions);

You can also specify the maximum and minimum number of threads in a pool. To set the maximum number of threads, you need to invoke the SetMaxThreads method.

ThreadPool.SetMaxThreads(int nWorkers, int nCompletions);

where nWorkers is the number of processing threads, nCompletions is the number of I/O threads. To set the minimum number of threads in a pool, use the SetMinTherads method.

ThreadPool.SetMinThreads(int nWorkers, int nCompletions);

The parameters here are exactly the same as in the SetMaxThreads method.

If, for some reason, the threads are not enough to perform the user’s tasks, the tasks will be automatically placed in a queue. As soon as at least one of the pool threads finishes its work, it will be redirected to execute tasks in the queue. If any of the threads completes its work before the rest, it will be sent back to the pool but not destroyed. This thread can be re-enabled at the first opportunity.

You can add a task to a thread pool’s queue in one of the following four ways:

  • Calling the QueueUserWorkItem method.
  • Calling asynchronous delegates BeginInvoke() and EndInvoke();
  • Using the BackgroundWorker class methods;
  • Using the Task Parallel Library (TPL) methods.

QueueUserWorkItem method

This method adds a task to the thread pool’s queue for execution and requests the required number of threads from the pool to perform this task. The name of the executable function, wrapped in a WaitCallBack delegate, is passed to the method as a parameter. The object of storing the task state data can be passed as the second parameter.

ThreadPool.QueueUserWorkItem(Job);

If the ThreadPool object does not exist at the time the method is invoked, it will be created. If the pool is already created and there is at least one free thread in it, then the task is passed to this thread. If several pool threads are free, then the pool will allocate these threads such that the task is executed as quickly as possible.

The following example uses all the basic methods of working with a thread pool – accessing a pool to display the maximum number of threads and sending a task to a pool for execution.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadPoolTest
{
class Program
{
static void Main()
{
int nWorkers; // number of processing threads
int nIOs; // number of I/O threads
ThreadPool.GetMaxThreads(out nWorkers, out nIOs);
Console.WriteLine("Maximum threads: " + nWorkers
+ "nMaximum I/O Threads: " + nIOs);
for(int i = 0; i < 10; i++)
ThreadPool.QueueUserWorkItem(Job);
Thread.Sleep(3000);
Console.ReadLine();
}
static void Job(object state)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("cycle {0}, is processing by thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(100);
}
}
}
}

The result of the example is shown in Figure 1. The program was executed on an Intel Core i7 4770K processor, which contains 4 physical and 8 logical processor cores.

Fig. 1 Result of program execution in a thread pool.

As can be seen from Figure 1, eight threads were allocated from the pool to the program – exactly the same number of logical processor cores available.

Features of a thread pool

Using a thread pool allows you to enhance the performance of a multithreaded application. A thread pool significantly reduces the cost of starting and stopping threads, increases the number of threads that are started and stopped, and can reuse completed threads.

However, a thread pool has a number of features that in certain situations can be considered as shortcomings:

  • All threads from a pool are background thread.
  • At the end of all the foreground threads of an application, the work of all threads from the pool will also be aborted, regardless of whether they have completed their tasks or not.
  • It is impossible to make a thread from a pool a foreground thread.
  • Threads in a pool do not have a name. The only thing you can get for a thread from a pool is its ID (using the ManagedThreadID property):

Thread.CurrentThread.ManagedThreadId

  • Threads from a pool cannot be assigned a name.
  • The priority of a thread in a pool can be changed, but once it finishes executing its task and is returned to the pool, its priority will be reset to the default value (normal).
  • When processing COM objects in a thread pool, there will be problems due to the fact that such objects require the use of single-threaded apartment (STA) threads, but all the threads of a thread pool are multi-threaded apartment (MTA) threads.
  • Threads in a pool are suitable for executing small tasks, but not for permanent work (such threads need to be created using the Thread class).
  • Blocking a thread from a pool will lead to the starting of additional pool threads; the pool will continue to execute the task but this will affect performance.

A thread pool is implicitly used in the following .NET constructs:

  • Windows Communication Foundation (WCF);
  • Interprocess communication component – .NET Remoting;
  • ASP.NET;
  • ASMX Web Services;
  • Event-based Asynchronous Pattern (EAP);
  • Timers: System.Timer and System.Windows.Timer;
  • Parallel LiNQ (PLINQ).

It should be remembered that all the features of a thread pool apply to the above constructs.

Do you need experts for your software development project? Contact us now

Asynchronous delegates

The C# function can be invoked for both synchronous and asynchronous execution. When the function is invoked synchronously, it is executed in the same thread as the main program. The synchronous function invocation itself occurs in the usual way – by specifying the function name and its arguments in brackets immediately after the name.

When a function is invoked asynchronously, the runtime environment CLR allocates for the function a separate thread from the thread pool and executes the function in this thread, while the master program continues to execute in the main thread. To execute a function asynchronously, it must be wrapped in an AsyncCallBack delegate. Next, this delegate must be invoked by calling the BeginInvoke method. You can use the EndInvoke method to get the value returned by the method and terminate the method.

The following example illustrates how to work with asynchronous delegates.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.Remoting.Messaging;
class Program
{
public delegate int MyDelegate(int x, int y);
static AutoResetEvent are = new AutoResetEvent(false);
static int WriteSum(int x, int y)
{
Console.WriteLine("Thread {0}: Sum = {1}",
Thread.CurrentThread.ManagedThreadId, x + y);
return x + y;
}
static void Summ(IAsyncResult async)
{
Thread.Sleep(3000);
// AsyncResult type from the System.Runtime.Remoting.Messaging namespace
MyDelegate func = ((AsyncResult)async).AsyncDelegate as MyDelegate;
int sum = func.EndInvoke(async);
are.Set(); // The Set method is used in thread synchronization and gives a signal to a thread to continue working
}
static void Main()
{
MyDelegate func = WriteSum;
// The C# compiler displays an AsyncCallback delegate to refer to the SumDone() method
IAsyncResult async = func.BeginInvoke(10, 10, Summ, null);
Console.WriteLine("Thread {0}: called throw BeginInvoke() waiting to complete SumDone()",
Thread.CurrentThread.ManagedThreadId);
are.WaitOne(); // The WaitOne method waits for a Set signal from at least one thread
Console.WriteLine("Thread {0}: finished his work",
Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
}

To run a function for asynchronous execution, you need to declare the delegate class first.

public delegate int MyDelegate(int x, int y);

where int written after the keyword delegate is the type of the value returned by the function. The arguments of the function are listed in brackets.

The AutoResetEvent class notifies the thread generated by the asynchronous delegate that an event has occurred by calling the Set method. The value false is passed to the event constructor if AutoResetEvent is not scheduled to be triggered immediately after it is created.

staticAutoResetEvent are = new AutoResetEvent(false);

Next, you need to create an asynchronous MyDelegate delegate, which was declared earlier. The created delegate will be named func.

MyDelegate func = ((AsyncResult)async).AsyncDelegate as MyDelegate;

The EndInvoke method of the func delegate is used to return the result of asynchronous function execution.

The Set method of the AutoResetEvent class gives a signal to a waiting thread that it can resume its work. The Set method works only with waiting threads. In any other state other than waiting, the method ignores the threads. The WaitOne method is used to enter a thread in a waiting state. The WaitOne method blocks the current thread until it receives a signal generated by the Set method.

The result of the example is shown in Figure 2.

Fig. 2 – Result of execution of an asynchronous delegate.

As can be seen from Figure 2, the asynchronous delegate is actually executed in a separate thread.

BackgroundWorker Class

The BackgroundWorker class is designed to start long-running tasks in a separate thread. This class is essentially a wrapper for the ThreadPool class and uses a thread pool in its implementation. BackgroundWorker is needed if there is only one task that needs to be executed in a background mode in a separate thread.

BackgroundWorker provides the following capabilities:

  • Implementation of the protocol for sending and receiving messages on task progress, completion or early termination.
  • Flag for cancellation of an operation without using the Abort method of the Thread class.
  • Can be placed as a component on a form in a Visual Studio form designer (implements the IComponent interface).
  • Can handle exception in the main thread of a NET app (without mandatory writing of the try {} catch block in the body of the delegate of the passed thread).
  • Can change the statuses of window controls without using InvokeRequired and Dispatcher.

How to use BackgroundWorker

You can take use the features of the BackgroundWorker class in two ways:

  1. To create an instance of the BackgroundWorker class.
  2. To create a class inherited from BackgroundWorker.

When creating an instance of the BackgroundWorker class, the following needs to be performed:

  1. Create this instance by invoking the constructor.
  2. Add a DoWork event handler.
  3. Invoke the RunWorkerAsync method and pass an instance of any class inherited from object to it as an argument.

Once the work is completed, BackgroundWorker will generate a RunWorkerCompleted event.

BackgroundWorker allows you to display the progress of an operation. To do this you need to:

  1. Set the value true for the WorkerReportsProgress property.
  2. In the DoWork event handler, periodically invoke ReportProgress, indicating the amount of work done and the remaining work.
  3. Process the ProgressChanged event by requesting the ProgressPercentage property of its argument.

Event handlers ProgressChanged and RunWorkerCompleted freely access the user interface elements.

If there is a need to cancel an operation being performed by BackgroundWorker, you need to:

  1. Set the WorkerSupportsCancellation property to true.
  2. Set the Cancel property of the DoWorkArgs argument to true.
  3. Request cancellation of the operation using the CancelAsync method of the BackgroundWorker class.

The example below illustrates all the common operations with BackgroundWorker:

using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker bw;
static void Main()
{
bw = new BackgroundWorker(); // we create a new instance of the BackgroundWorker class
bw.WorkerReportsProgress = true; // we set support for progress of operations
bw.WorkerSupportsCancellation = true; // we set support for operation canceling
bw.DoWork += workfunc; // we add DoWork event handler
bw.ProgressChanged += Progress; // we add state change event handlers
bw.RunWorkerCompleted += Completed; // we add a shutdown event handler
bw.RunWorkerAsync(null); // We run BackgroundWorker
Console.WriteLine(
"Press Enter during five seconds to abort the process");
Console.ReadLine();
if (bw.IsBusy) // if the Enter button is pressed
{
bw.CancelAsync(); //cancel operation
Console.ReadLine(); //read Enter key pressing
}
}
static void workfunc(object sender, DoWorkEventArgs e)
{ // function executed by BackgroundWorker
for (int i = 0; i <= 100; i += 20)
{
if (bw.CancellationPending)
{ // here we process operation cancellation request
e.Cancel = true; // here we cancel the operation
return;
}
bw.ReportProgress(i); // here we declare the status of the operation
Thread.Sleep(1000); //and put the thread to sleep for a second
}
e.Result = 1989; // will be passed to RunWorkerComрleted
}
static void Completed(object sender, RunWorkerCompletedEventArgs e)
{ // BackgroundWorker completion event handler function
if (e.Cancelled) // if user aborted work
Console.WriteLine(
"Task processing by BackgroundWorker was aborted by user!");
else if (e.Error != null)
Console.WriteLine("Worker exception: " + e.Error); // if work was aborted due to exception
else // if work was executed completely
Console.WriteLine("Work is complete. Result is " + e.Result + ". ");
Console.WriteLine("Press Enter to exit...");
}
static void Progress(object sender, ProgressChangedEventArgs e)
{ // function that displays the status of work being performed
Console.WriteLine("Proceed " + e.ProgressPercentage + "%");
} //ProgressPercentage - method of the ProgressChangedEventArgs argument of the BackgroundWorker class
}

Display of the application when the Enter key is pressed (BackgroundWorker was aborted by the user) is shown in Figure 3.

Fig. 3 – Display of application when BackgroundWorker was interrupted.

Figure 4 shows the display of the application if the task that BackgroundWorker was performing was not interrupted.

Fig. 4 – Display of the application in the case when BackgroundWorker operation was not aborted.

BackgroundWorker inheritance

The BackgroundWorker class allows you to inherit user classes from it. This class provides the OnDoWork virtual method, which the developer can override in his own way.

using System.Collections.Generic;
using System.Threading;
using System.ComponentModel;
namespace BgWorkerInherit
{
public class Client
{
public Jamshut Tile (int foo, int bar)
{
return new Jamshut(foo, bar);
}
}
public class Jamshut : BackgroundWorker
{
//You can add typed fields.
public Dictionary<string, int> Result;
public volatile int Foo;
public volatile int Bar;
public Jamshut()
{
WorkerReportsProgress = true; //Jamshut will show the progress of its work
WorkerSupportsCancellation = true; //Jamshut can interrupt work
}
public Jamshut(int foo, int bar) : this()
{
Foo = foo;
Bar = bar;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
ReportProgress(0, "Bossy, Jamshut begins to put tiles");
bool finished = false;
int percentage = 0;
//Jamshut begins to work
Thread.Sleep(1000);
while (!finished)
{
if (CancellationPending)
{ //If a request is received to cancel the operation, Jamshut will stop its work
e.Cancel = true;
return;
}
Thread.Sleep(1000);
if (percentage < 100) percentage += 10;
// Jamshut reports on the progress of work
ReportProgress(percentage, "Proceed "+percentage+" %");
}
ReportProgress(100, "Bossy, come to see. Jamshut finished his work...");
e.Result = Result;
}
}
class Program
{
static void Main(string[] args)
{
}
}
}

The code that created the Jamshut class object will have an already configured background operation handler that will report on the progress of its work and support its cancellation. In addition, the Jamshut class can update all the elements of the application’s graphical user interface without using Control.Invoke (in WinForms) and Dispatcher.Invoke (in WPF) methods.

Conclusion

In this part of the article, we have looked at the methods of background and asynchronous execution of threads in .NET apps. These methods have a number of advantages and disadvantages and that is why they are not always convenient to use. But in general, background and asynchronous execution of threads provides ample opportunities for execution in separate background threads of both short- and long-running tasks.

In part 3 of this article, we’ll look at .NET’s Task Parallel Library (TPL) and Parallel Language Integrated Query (PLINQ), which enables you to parallelize separate code snippets or database queries.

What .NET Threads Are. Part 1

Ways Of Creating Multithreaded Applications In .NET (Part 1). What .NET Threads Are

With the advent of multi-core processors, multithreading has become almost indispensable in the development of applications. It is multi-threading that gives significant performance gain when using multiple processor cores.

However, multithreading comes with a lot of hidden pitfalls that are very unpleasant for inexperienced developers. Therefore, we have decided to make a series of articles devoted to multithreading methods in .NET applications using the C# language as an example.

In the first part, we’ll talk about multitasking and multithreading, we’ll consider the architecture of multi-core processors and how processor cores are arranged in an operating system. We’ll also review operating system tools for creating multithreaded applications, and we’ll take a closer look at the Thread class.

What is multitasking and multithreading?

Multitasking has become quite a natural phenomenon in modern operating systems. When several applications are running at the same time, the operating system can quickly switch between them, giving them CPU processing resources in turns. This creates the illusion that several programs are running simultaneously. This separation seems inconspicuous since neither the person nor the fastest Internet connection can work at the speeds with which modern processors process information.

Multithreading is the same thing as multitasking but within one application. The operating system switches between different parts of the same application quickly, thus creating the illusion that it is executing them simultaneously.

If you’re interested in more, read Microsoft Roslyn – using the compiler as a service

Architecture of modern computers

In the 2000s, when the CPU clock speeds grew rapidly, it seemed that nothing could stop this growth. Some experts predicted that the 10 GHz mark will be exceeded by 2010. This growth was proportional to reduction in the size of processor transistors, while an increase in processor power in those times was significantly ahead of Gordon Moore’s predictions (see Moore’s law).

However, before long, engineers encountered problems – substantial increase in heat release and fundamental limitations on transistor size. As a result, further increase in performance by improving CPU clock speed became practically impossible, and the clock speed remained at the 3-5 GHz mark today.

Engineers had to look for other ways of improving CPU performance. They found such an effective solution in multiprocessor information processing. If you cannot make the processor faster, why not add one more processor? In this case, you don’t need to create such a processor in the form of a separate device. The easiest way is to create such processors within one module so that they all have equal access to shared memory. Such processors were called physical processor cores.

Logical processor cores and hyper-threading

Operating systems operate on logical processor cores, sharing the time resources of each of the processor cores between processes and threads. A logical processor core may not always match with a physical processor.

In 2002, the Intel Pentium 4 processor introduced the Hyper-Threading technology for execution of commands. Hyper-Threading involves execution of multiple command threads by one physical processor core. In this case, the operating system sees each thread as a separate logical core. Dual-threaded hyper-threading works by adding another set of registers, an instruction pointer, and an interrupt controller into the physical core of the processor. Here, the number and set of execution units in the core remains unchanged.

Hyper-threading appeared as a solution to the problem of frequent downtime of the computational pipeline of Intel Pentium 4 processor, associated with excessive increase in the number of information processing stages in this pipeline.

The reasons for such downtime were:

  • The branching instruction was incorrectly predicted when executing conditional and unconditional branches.
  • There was a miss when accessing the processor’s cache and data needed to be loaded into the cache from the RAM.
  • The result of the previous instruction, which is still executing, is needed to execute the next instruction.

It should be understood that hyper-threading threads are not full-fledged physical processor cores, so they do not give multiple increase in performance. On average, the performance gain from hyper-threading is 1-30%, depending on the task being solved. In some tasks, there can be no performance increase at all. Nevertheless, hyper-threading is used in processors to this day, for example, in Intel Core i3, Core i7, Atom, Pentium, AMD Ryzen, and others.

If you’re interested in more, read .NET Core Framework Complete Review

Processes and threads in operating systems

The operating system works with logical processor cores, not knowing about their physical implementation. It sees the physical processor cores and hyper-threading threads as the same. A clear example of this is a screenshot of Windows Task Manager for a quad-core (4 physical cores + 4 hyper-threading threads) of the Intel Core i7-4770K processor in Windows 7 (Fig. 1).

Fig. 1 – Screenshot of the Windows Task Manager for Core i7-4770K.

The main program object of an operating system is the process. A process is an executable instance of an application that owns system resources (for example, RAM resources or I/O threads).

Each process can have one or more threads. Each thread executes part of the process code and has its own stack and registers. Threads can only access process resources and share them among themselves. The structure of a multithreaded program is shown in Fig. 2.

Fig. 2 – Structure of a single-threaded and multithreaded program.

At the same time, it is much faster to switch between threads than between processes during execution. Therefore, in terms of computing resources, it’s more profitable working with threads than working with processes. In addition, threads are supported by most operating systems and software platforms, for example:

  • WIN32 API Threads (Windows)
  • Cocoa Threads (iOS)
  • Multiprocessing Services (iOS)
  • Java Threads (Android)
  • POSIX Threads (GNU/Linux)
  • C Runtime Library (C)
  • OpenMP (C++, Fortran)
  • Intel Threading Building Blocks (C++, Fortran)

We will consider the technology for working with threads in .NET using C# as an example.

Thread class

The System.Threading namespace contains all the tools for low-level thread creation and management. First, we add this namespace to the project.

using System.Threading;

If threads have not yet been created, then at least one thread is already executing in the application. Let’s call it Main. To create another thread, we need to create a new Thread object.

Thread t1 = new Thread(GetThreadld);

In this case, the constructor of this object must pass the name of the function whose code will be executed in this thread. Here, it is the GetThreadId function. This function is passed as an object (in other words, a delegate) to the constructor’s argument. In this case, a function represented as a delegate has neither parameters nor return value. However, we can get out of this situation. For example, we can give a command to start a thread and simultaneously pass function parameters.

t1.Start("1");

Until the Start command is given, the thread will not start execution. In this case, the GetThreadId function can pass only an object as a parameter. The GetThreadId itself is declared as:

static void GetThreadld(object data)

A thread can be assigned a priority – both before its start and during execution.

t1.Priority = ThreadPriority.Lowest;
t2.Priority = ThreadPriority.BelowNormal;
t3.Priority = ThreadPriority.Normal;
t4.Priority = ThreadPriority.Highest;

ThreadPriority is a listed type here.

After all the threads have started, you need to call a function that is waiting for completion of their work. This is the Join function. Once the Join for all threads is executed, the threads will be terminated and destroyed. .NET automatically frees any resources that were occupied by these threads.

//waiting for all threads to finish executing
t1.Join();
t2.Join();
t3.Join();
t4.Join();

After the threads have finished executing, the main thread will again take over code execution completely.

Example of how the Thread class works

The following example displays 1000 messages from different threads with different priorities. Threads write their numbers to the console 1000 times each.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
static void GetThreadld(object data)
{
// now the Main thread will display the received string (its number) one thousand times
for(int i = 0; i <= 1000; i++)
Console.Write(data);
}

static void Main(string[] args)
{
// we create 4 threads, we transfer as parameter the name of the function executed by the thread
Thread t1 = new Thread(GetThreadld);
Thread t2 = new Thread(GetThreadld);
Thread t3 = new Thread(GetThreadld);
Thread t4 = new Thread(GetThreadld);

// we assign priorities to threads
t1.Priority = ThreadPriority.Lowest; // lowest
t2.Priority = ThreadPriority.BelowNormal; // below normal
t3.Priority = ThreadPriority.Normal; // normal
t4.Priority = ThreadPriority.Highest; // highest

// we run each thread and pass the thread number as a parameter
t1.Start("1");
t2.Start("2");
t3.Start("3");
t4.Start("4");

Console.WriteLine("all threads have started");
// waiting for all threads to finish executing
t1.Join();
t2.Join();
t3.Join();
t4.Join();

Console.ReadKey(); // Until the user presses the key, the program will not end (so that you will have time to view the result)
}
}
}

The program execution result is shown in Fig. 3.

Fig. 3 – Visual illustration of the work of threads with different priorities on a quad-core processor.

The example in Fig. 3 shows three facts:

  1. Creation of threads is a fairly time-consuming operation. First, thread 1 with the lowest priority was created and immediately launched for execution. Then the other threads were created and launched in turns.
  2. Threads are terminated according to their priority: the thread with the highest priority (4) ended earlier than the other threads.
  3. If a multithreaded program is running on a multi-core processor, the priority of threads becomes less significant here than on single-core processors, since threads will be allocated among all the processor cores.

Background and foreground threads

Threads can be foreground and background. The difference between foreground threads is that the program does not end until all the foreground threads have been executed. Background threads do not hinder the completion of a program and are terminated together with it, even if the process that the background threads were executing have not yet been run.

To find out whether a thread is a background or foreground thread, use the IsBackground property.

bool bg = Thread.CurrentThread.IsBackground;

where CurrentThread is a static method of the Thread class, which returns a link to the thread that is currently an active thread.

By default, all threads are created by foreground threads. But anywhere in the program code, you can make the thread to become background and vice versa.

t2.IsBackground = true;

Possible errors when working with the Thread class

Despite the simplicity of working with the Thread class, many novice developers make gross errors when creating multi-threaded applications.

Error 1

The most common mistake made by inexperienced developers is that they try to catch exceptions that occur in child threads, using the try { } catch block to wrap its call from the parent thread. The point is that in this case, all exceptions in the parent thread will be processed, while exceptions in child threads will remain unprocessed and lead to immediate termination of the application. The listing below shows how not to catch exceptions in multithreaded applications.

try
{ // This code is incorrect
t1.Start("1" );
t2.Start("2" );
t3.Start("3" );
t4.Start("4" );
t2.IsBackground = true;
t3.IsBackground = true;
t4.IsBackground = true;
Console.WriteLine(" all threads have started ");
//waiting for all threads to finish executing
t1.Join();
t2.Join();
t3.Join();
t4.Join();
} catch (Exception e)
{ // only exceptions in the parent thread will be processed here
Console.WriteLine(e.ToString());
} // exceptions in child threads will not be processed and they will stop the application

To catch all exceptions in child threads, the try {} catch block must be located inside the function that will be passed to the child thread for execution, as in the listing below:

static void threadID(object data)
{
try
{
// now the thread will display the received string (its number) one thousand times
for (int i = 0; i <= 1000; i++)
Console.Write(data);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

Error 2

The second error is the attempt to access the application interface from the child thread. When developing applications with a graphical user interface (for example, WinForms or WPF applications), there is always a main thread that monitors the state of the GUI elements. Only this thread can change the state of the interface elements. Any other thread, when accessing these elements, will immediately throw an exception.

In WinForms applications, the compiler will mark as erroneous the code that accessed the controls from another thread. In additional information, the following will be written about this error:

“Additional information: Cross-thread operation not valid: Control ‘textBox1’ accessed from a thread other than the thread it was created on”.

In WPF applications, the situation is even worse. This will throw up an InvalidOperationException exception during execution of the application with the description “The calling thread cannot access this object because its owner is another thread” (Fig. 4).

Fig. 4 – An example of an exception when accessing the elements of the WPF application interface from another thread.

If there is still a need to change the interface elements, there are fairly simple solutions in this case. If you need to access the interface in a WinForms application, you will need to first perform a check by calling the InvokeRequired method from the interface element. If the InvokeRequired condition is true, then execute the Invoke method (see the listing below). If Invoke has already worked, then the interface element can be accessed directly.

void ControlAccess()
{
if(textBox1.InvokeRequired)
textBox1.Invoke(ControlAccess);
else
textBox1.Text = "test";
}

Calling Invoke without InvokeRequired check will also throw an exception.

In WPF applications, special object Dispatcher is used to access interface objects from other threads. To organize a call, you need to connect the following System.Windows.Threading space.

using System.Windows.Threading;

Next, we need to wrap the application interface from another thread with the static Invoke method of the Dispatcher class.

this.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate() { Cons.Text = "Industrial";});

Here “this” is a pointer to the current window whose interface elements are accessed. DispatcherPriority is an enumerated type that is responsible for interface access priority. Type gradation is exactly the same as when creating threads.

With the delegate() function, we declare an anonymous function and pass code to it with direct access to the interface elements. After declaring the anonymous function, it must be cast to the ThreadStart type (casting to a type is indicated in parentheses before the variable or function). In this case, accessing the interface will not throw any exceptions in the WPF application.

Error 3

A fairly common mistake is the lack of control over the completion of threads. The point is that the .NET Common Language Runtime (CLR) environment does not know if the thread will continue to perform any actions after it has completed all the work. Therefore, all responsibilities for completing the work of threads and their destruction lie on the shoulders of the developer.

The developer is obliged to ensure correct completion of all application threads in case the application was closed (including abnormally). If this is not done, the application’s parent thread will be terminated, while the child threads will continue to execute (even when the application window is already closed). At the same time, they will consume system resources, and after closing the application window, you can stop them only through the task manager.

This can lead to amusing situations. For example, the author of this article used to study the multimedia capabilities of WPF and worked with the MediaPlayer class, which can open and play *.mp3 files. He did this in a separate thread. If you don’t take care of the ending of the thread that plays music, then even after closing the application window, the music will continue playing.

Conclusion

Modern multi-core processors are designed such as to execute a large number of processes and threads at the same time. Nevertheless, this operation is quite resource-intensive.

Despite all the simplicity and efficiency of working with the Thread class, multithreaded programming is fraught with a lot of dirty tricks, and the developer risks running into unexpected program behavior if he/she doesn’t know about the tricks.

In the following parts of this article, a thread pool that saves significantly on the computing cost of creating threads will be considered. Methods of thread synchronization, multi-sequencing of cycles and database queries will also be considered.

How To Design A Landing Page That CONVERTS

Simple steps to increase conversion rate

Technically speaking, a landing page is a HTML document that contains CSS, text, pictures, videos, and sometimes scripts. This page is not that much different from the normal websites. But from the business point of view, certain expectations are placed on a landing page – it must convert. An end user should be able to quickly get all the information he needs about a product and take an informed decision to buy or not to buy on the landing page.

Landing pages work most efficiently when you need to compel users to register on the site or leave their contact information. There is no better solution if your task is to compel users to download a software product.

When it comes to sales, landing pages fully justify any investments, when you need to sell a particular product or service in a particular situation – a promo offer, clearance sale, and entry into a new market.

Structure of a high converting landing page

The structure of a landing page is simple and linear. Let’s consider three parts: the first screen, the body of the page and the last screen. The classical first screen includes a background image, contact information, logo, headline and a button.
A product can be effectively used on the first screen as the main image. Background images on the first screen make a great impression on users. No wonder Apple uses such approach – see Fig. 1.

Fig. 1 – An iPhone used as a background image on the first screen. Source: www.apple.com

After you engage the user in studying your page, you need to provoke his trust and push him to buy. The following typical blocks are targeted at this.

Team. If you provide services, it is important for the customer to know exactly with whom to communicate if he decides to contact you, and who will handle his inquiries. The best way to gain the trust of a potential customer is to introduce yourself and tell him about your team.

Fig. 2 – Photos of team members with links leading to their portfolio. An excellent demonstration of professionalism. Source: http://islreview.com/

Text description of a product. You can use text blocks to describe the advantages your product have over competitors. An important rule here is that the blocks should be placed closer to the end of the page in order not to influence the first impression (a lot of text in the beginning may seem boring), but also not on the last screen.

Fig. 3 – Detailed description of what is included in the ticket price. Source: www.valiocon.com

Video. Placing video clips as the background of a landing page could be both useful and extremely harmful. Here’s what you need to understand: the video should not interfere with perception of other information, neither should it slow down the loading of the page. Besides, you should think in advance how you would compel the visitor to watch the video, because he would need good reasons to do so.

Fig. 4 – The atmosphere of the video ideally repeats the emotions that are evoked by the product. Source: www.getrest.co

Reviews. Positive reviews from satisfied customers – if the authenticity of such reviews is in no doubt – lead to stronger sales. The problem is that no one reads these reviews if presented in a mediocre and unattractive manner. Ensure that blocks featuring the opinions and reviews of satisfied customers or prominent people arouse interest and trust.

Fig. 5 – Stylish and brief quotes help to gain trust.

The final screen of the landing page is designed to summarize all your advantages and encourage the visitor to become a buyer – via a treasured button with a call to action.

Call to action

Each element of the landing page directs the user to the mouth of the conversion funnel, but only one call to action is needed. Several calls to action ruin the conversion rate ruthlessly. Suggest to users to make one unique and concrete action – is it not for this reason that the landing page was developed? Let’s examine this element in more detail.

A call to action should highlight the real benefit to the customer in a language that he understands. The client should be able to get the said benefit immediately after clicking on the button.

The action should be extremely simple: if the goal of the landing page is to collect phone numbers, then no other field should be included in the form. You only need to ask the user what his name is in addition to collecting his phone number. If the aim of the landing page is to distribute a software product, then the call-to-action button should initiate a download to the computer.

Fig. 6 – Having one field for email address and one button is a great example of how to avoid asking the user for unnecessary information. Source: www.monkop.com

There is one more rule – the more complex a product is, the simpler the action should be. It is ineffective to accompany complex products with calls for immediate purchase. If you are selling heating equipment, then simply ask the visitor to leave his phone number, and not try to sell an expensive device straight away through one web page.

Fig. 7 – You shouldn’t try to sell a camera worth $5,995 and its accessories in one page. It’s better to collect contacts from that user. Source: www.blackmagicdesign.com/products/blackmagicursaminipro

If you make your call to action different from those offered by competitors by adhering to the above simple rules, then the number of your leads would grow substantially.

Fig. 8 – A great call to action in the footnote. You can immediately see the price on the button.

AIDA and PMHS

AIDA is an acronym that stands for:

  • Attention
  • Interest
  • Desire
  • Action

It is a marketing model that describes a person’s decision to buy. This model works flawlessly. Implementing it into the structure of a landing page is very simple.

Blocks that capture attention are located on the first screen (headline, attractive background image). They are followed by those that arouse interest (display of the product and its advantages). You generate desire with discounts and time-limited actions, while buttons and forms lead to action.

PMHS stands for:

  • Pain
  • More pain
  • Hope
  • Solution

It is a design scheme for promotional materials, which helps to create a converting page structure. This scheme migrated to the Internet from infomercial (teleshopping).

First, the pain of a potential customer is described. If you sell toothpaste, then tooth problem is your customers’ pain. Then the pain intensifies, the consequences of these problems are described. In the end, there is a ray of hope in the form of your paste and a solution – mail delivery for $25. Remember, PMHS is a negative motivation that does not suit all companies and products.

You can use both tools to create a landing page structure and compose blocks on the page for maximum effect.

How to write high-converting headlines

Headline is a key element of a landing page. Before you sell your products, try to grab attention and spark interest. Only after reading a strong headline that a person would continue to study the page.

4 U’s – technique for writing high-converting headlines.

The technique highlights the four features of a strong headline. For an example, we shall use the phrase “Buy tires” and modify it with four elements: Useful, Urgent, Unique and Ultra-specific.

Usefulness
Demonstrate the benefits and point out the solution to the problem. Buying quality tires is beneficial in terms of safety on the road. The original headline “Buy tires” is therefore replaced with “Improve safety on the road”.

Urgency
Create a sense of urgency by adding a time parameter. People value their time. Show them that you can save their time. If it would take half an hour to replace the tires, then write: “Improve safety on the road in 30 minutes”.

Ultra-specificity

Speak clearly and use numbers. Be specific so that the buyer would know what he is paying for. Show the benefits using numbers: “Improve safety on the road by 25% in 30 minutes”.

Uniqueness
Tell why the product is unique. Let the reader understand how the benefits are achieved. The sentence should not look magical. “Improve safety on the road in 30 minutes with Japanese rubber”.

The main thing is to convey the value of the product to the reader. This technique serves as a farewell speech, and not a strict rule. It is not always necessary to use all the four U’s – sometimes you can do with three or even two. If the headline turns out to be cumbersome, you can put some of the information into a sub-headline.

Fig. 9 – An example of a strong headline with an informative sub-headline. Source: www.close.io
Fig. 10 – An example of a weak headline. The reader can understand the features of the product, but not the benefits from the beginning of its use right away. Source: www.sensortower.com

Some tips to increase conversion rate

1. Contextual advertising is the most common source of traffic for landing pages. The headline of a landing page, which welcomes visitors, should create the same impression as the advertising text that brought the user. This would make the user understand that he moved exactly where he wanted. Never allow the advertising text and the headline to create different impressions – this could lead to many visitors coming and leaving immediately.

2. Do not use stock images that can be found on many other sites. This is fraught with the fact that your landing page may get lost in a great lot of other headlines of potential customers. But even the uniqueness of the image is not enough – it should reflect or highlight the essence of your product.

Fig. 11 – Background image with people, though friendly, but uninteresting, boring, and does not reflect the essence of the page.

3. Even such a trifle as usual spelling errors can seriously damage the image of a company in the eyes of a potential client. Watch for both the grammar and the style of the text.

4. Landing page – a short and concise dialogue with a potential client. Using minimum number of blocks, you need to quickly make a person take the target action. If he gets distracted for even a moment, you can lose him. Therefore, all the elements of the page should serve a single purpose; there must be a reason for placing anything on the page.

5. If you don’t know why you need this or that block or element, safely remove it. Conduct tests to determine which elements of the page are not good enough and are negatively interfering with conversion rate.

6. Use social networking sites. Unobtrusively invite visitors to share your page and don’t hesitate to brag about the number of Likes you have on Facebook.

The main thing is to be honest with the visitor. If you undermine confidence, then your landing page won’t be able to restore your reputation. Do not lie or place unreliable or unverified information. Inconsistency between the real and declared price on the site is a common reason for refusal after a call.

Have a success in your sales!

.NET Core Framework Complete Review

Developing Cross-Platform Apps Faster and on Any Platform

At the end of the last century, Microsoft, one of the most successful software development corporations, faced the problem of a huge number of incompatible languages, environments and programming technologies. At the same time, the development process was rigidly focused on a specific programming language. Also, across different languages, there was a different set of incompatible technologies. Above all, these technologies were gradually becoming obsolete.

There was a need to implement new programming tools that would fully support the object-oriented approach, exceptions handling and garbage collection. The growing popularity of the new Java software platform by Sun Microsystems surely added some fuel to the fire.

What was there before .NET Core?

In 1999, Microsoft began the development of a new unified platform, NWGS, later called the .NET Framework. This software platform, despite all the weaknesses and inoperability of the first versions, has become a unique product, combining many benefits. The main advantages of the platform:

  • Hardware-independent execution environment with the ability to compile just-in-time (JIT). This means that an application written in languages that support .NET can be run on processors of different architectures, in case there is a translator from the .NET MSIL language into the command codes of this processor.
  • Support for compatibility of program fragments written in different languages. For example, in C#, you can create your own class, inherited from a class written in Visual Basic, and call a method written in Managed C++. This all works without error.

As the .NET Framework evolved, it acquired new technologies and development capabilities. In version 2.0 there were WinForms and ASP.NET, in the 3.0 version there were WPF and WCF, the 3.5 version gave us LInQ, in version 4.0 TPL and PLInQ saw the light, and in version 4.5 API for Windows Store applications was added.

In 2002, the first version of the .NET Compact Framework was released. It was intended for mobile devices run by Windows Mobile. The .NET Compact Framework is formally a subset of the .NET Framework, but it actually contains its own application model, framework, and runtime environment, that is significantly different from the similar .NET Framework model.

Subsequently, all new “subsets” of the .NET Framework were born. They were architecturally and functionally different from the desktop .NET version. These subsets are familiar to all .NET developers. They are: Silverlight, Windows Phone, Windows Store, .NET Micro Framework, and ASP.NET. The situation is even stranger for the last one: ASP.NET of version 4 and ASP.NET of version 5 are two different platforms, each with its own application model, framework, and execution environment (Figure 1).

Figure 1. Example of the different .NET verticals

Of course, all the platforms mentioned have a number of common APIs because they all once were separated from the desktop version of the .NET Framework. But their evolution caused the growth of differences between them, and Microsoft had to come up with increasingly sophisticated “crutches” to ensure compatibility and uniformity of their APIs. The compatibility problem arises when you need a software product that can work on several platforms. This raises the question of the availability and compatibility of the API in each of these platforms.

In addition to the mentioned “subsets” of .NET that run exclusively on Windows, there are also implementations of the .NET Framework for Linux systems, the most famous of which are Mono and DotGNU. These are created by communities of enthusiasts; Microsoft did not participate in their development in any way. Each of these implementations also represents a “subset” of .NET, with its own application model, framework, and runtime. Porting applications from the Windows version of the .NET Framework to Mono or DotGNU is as difficult as the development of an ASP.NET application version based on its desktop implementation.

It turned out that Microsoft eventually gave birth to a whole “zoo” of similar, but at the same time different, platforms with different APIs, application models, and execution environments in order to create a single software platform with full language and technology compatibilities. The .NET Framework, which Microsoft considered a salvation from the “zoo” of incompatible languages and technologies, eventually itself became the “zoo” of APIs and implementations. Microsoft again faced the challenge of creating a single software platform for all development methods that exist in the .NET Framework. This platform is .NET Core.

What is .NET Core?

.NET Core is a modular cross-platform version of .NET Framework with the ability to port applications to other platforms and operating systems. In this case, the already created code is used to the maximum during the porting process, while the use of APIs specified for a particular platform is minimized. However, .NET Core does not replace the .NET Framework, but is just a version of it (a subset). Also, .NET Core does not replace Mono on Linux-like operating systems – both projects are developing in parallel.

This is achieved by using portable class libraries (PCL) with the most common form of API for all target platforms. At the same time, implementations of the application, including the framework itself and the execution environment, remain different, although they are subsets of .NET. Appeals to the API are particular for a specific platform (in the case of designing a cross-platform project) and are separated by special preprocessor directives:

#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed
+= HardwareButtons_BackPressed;
#elif WINDOWS_APP
// Ignore. Windows Store doesn't have support for this.
#else
#error Unknown platform
#endif

where WINDOWS_PHONE_APP is the preprocessor symbol declared in the project. It can be found in the project properties (the Build section).

Beginning with 2013 Update 2 version in Visual Studio, it became possible to create universal applications for Windows that can be run on several platforms, due to PCL.

.NET Core is creating by the .NET Foundation community, which, in addition to Microsoft programmers, includes many independent developers, including the Mono Community developers.

Everyone can participate in the creation of .NET Core. The participation rules are published on GitHub. The project with open source is published on GitHub as well. .NET Core is a free software under the licenses of MIT, Apache 2.0 and Creative Attribution 4.0 (for some modules).

Portable Class Libraries (PCL)

In the .NET Framework, the core of the system is the extensive mscorlib library. It contains a lot of APIs and their implementations, some of which are not required in other target platforms (which differ from the desktop version) and others are not supported by these platforms. It turns out that on another target platform (for example, in Silverlight) there is a completely different mscorlib library. The situation is the same for other .NET libraries. Unlike the .NET Framework, the .NET Core has a flexible architecture of PCL, designed with significant code decomposition. At the same time, the dependencies between the libraries are clearly monitored by the .NET Core itself.

Each PCL is responsible for a specific .NET module and no more than that. Each PCL has its own independent assembly version, and new APIs are available only in new PCL versions.

This allows the target platform to choose the PCL modules independently. It is also important to note that the platform cannot support any PCL partially – it either supports it or it does not.

Also, the main principle of .NET Core is based on PCL, and there are uniform APIs for various .NET implementations. However the .NET implementations have not disappeared. They continue to exist and they are as different as before, but access to them can be done through APIs which are common to all of these implementations.

PCL allows you to implement the same code in several target .NET Core platforms.

If you’re interested in more, read How an IT Pro Makes His Life Easier Using TFS 2015

Unified BCL is the Cross-platform Kernel for .NET Core

BCL contains an API that is uniform for the entire .NET Core and for all its implementations. For example, most of the .NET Native API used to create applications for mobile devices and ASP.NET 5, on which the server side of web applications is written, contains BCL, and it is the same for both technologies.

BCL is an intermediate layer of assemblies on MSIL, common for all .NET implementations. Above BCL, there are APIs specific for each particular platform (so-called “application models”), for example, WinRT interop for .NET Native and MVC for ASP.NET 5.

Below BCL there is a layer of adaptation to various .NET implementations to the performing environments, for example, CLR (CoreCLR) or .NET Native. The CLR compiles the MSIL code into the target platform command system during the execution of the application (JIT compilation).

Unlike the CLR, .NET Native compiles the MSIL code, together with the .NET libraries, into the target platform command system, even before it reaches this platform, and launches on it. As you can see from the description above, CoreCLR and .NET Native are two completely different .NET execution environments, but the BCL is the same for both and interacts with them only through the adaptation layer.

Currently, .NET Core BCL is being developed under the name of .NET Standard.

Compatibility Issues in the .NET Framework

The traditional .NET Framework is distributed as a single, indivisible software product. It is installed on the device entirely and it is removed from the device entirely. The new version replaces the previous one, with all the ensuing consequences. However, the new version of the .NET Framework can disrupt the normal operation of the application written in an older version. For example:

  • If a new interface is added in the new version to the existing type of the .NET Framework, there may be problems with the serializing of this type;
  • If an additional overload has been added to the existing method in the new version of the .NET Framework, then there may be a problem with the reflection of this method;
  • In the case of renaming an internal type to the .NET Framework, the application’s performance may also be compromised if the type name is determined by the toString() method.

Since the release of the new version of the .NET Framework, Microsoft has been trying to make it compatible with the previous version. But even if the probability of failure is extremely low (less than 0.1%), then there may be millions of such failures, because the .NET Framework is currently used on billions of devices.

NuGet – Distribution Mechanism and Modularization Basis of .NET Core

Unlike .NET Framework, .NET Core is presented as small NuGet packages, and each of them, as a rule, is responsible for any library or namespace. For example, if in .NET Framework the System.Colections.Generic namespace was a part of a large mscorlib library, then in .NET Core it is a certain NuGet package.

  • Every NuGet package has its own name and version.
  • Every NuGet package can be updated to a new version without updating other .NET Core components.
  • NuGet packages can be downloaded and installed individually from the website nuget.org without installation of a new .NET Core version.

Currently the nuget.org web page contains more than 800,000 .NET Core libraries. But this doesn’t mean that you would have to download .NET Core components from the website and install them separately every time a new application on .NET Core needs to be developed. All the NuGet packages included in .NET Core are installed alongside the installation of .NET Core and have the same version as the current version of .NET Core. Additional packages or packages of a newer version are downloaded and installed separately from the installation of .NET Core.

Additional NuGet packages that are not included in the current .NET Core version are circulated with the application after downloading. There is no need for NuGet to download its packages from the Internet. There is an autonomous installer for NuGet that is included in Visual Studio. Any plug-in in .NET Core can be replaced by a newer one without the installation of a new version of the framework. If a .NET Core plug-in works insecurely, NuGet can roll it back to an older version without disrupting the work of other .NET Core components.

Thus, .NET Core is a framework adjusted for every application. Every .NET application uses only these .NET Core libraries, which are required. The libraries that are common for all .NET applications are presented as NuGet packages within .NET Core. Additional .NET Core libraries are circulated together with applications.

Integration with Other .NET Platforms

.NET Core is a subset of .NET Framework and must be compatible with its other subsettings. The .NET platform is fully compatible with .NET Framework 4.6 and fully realizes its function. In time, .NET Core will develop faster than .NET Framework, but both projects will develop simultaneously. All the new technologies will be tested on .NET Core, and only then will they be adapted to .NET Framework.

Mono is a subset of .NET Framework released in Linux and MacOS. The Mono community is building up support for .Net Core release on these operating systems, at most, integrated with Mono.

Windows Store and Windows Phone are subsets of .NET Core as well, and contain their own models of applications over BCL and their own runtime (.NET Native).

Other .NET platforms can be compatible with .NET Core as well. It is achieved either by the usage of PCL or by the creation of a common project and the adaptation of code with the help of #if directives.

.NET Compiler Roslyn as a .NET Core Part

Particularly in .NET Core, a new compiler, Roslyn, is used, written for usage in .NET Core. Roslyn allows the connecting of each stage of code compilation and .NET application building through API.

The possibilities of Roslyn are described in more detail in the article Microsoft Roslyn – using the compiler as a service.

Among the most interesting Roslyn possibilities we can point out are the building and reprogramming of a syntactic tree, the generation of source code by this tree and the possibility of using C# and Visual Basic as script languages (with the use of REPL).

.NET Core gave Roslyn its own namespace of Microsoft.Net.Compilers and its own NuGet package, which corresponds to this namespace. On the basis of Roslyn, a freely distributable cross-platform IDE with Visual Studio Code open source code was developed.

ASP.NET Core – a New Framework for Web Applications

Despite its crudity, the ASP.NET becomes a prospective platform for web service development. This is facilitated by more compact code, better scalability and the very high efficiency of a new platform. Along with that, Microsoft has refused many technologies in ASP.NET Core which were used in ASP.NET. These are System.Web namespace, Web Forms, Transaction Scope, WPF, and WinForms. Instead, .NET Framework provides a flexible web application model, with the use of MVC and WebAPI subsystems.

If the earlier ASP.NET, based on System.Web.dll, ran only on Windows and IIS, then at present, relying on benchmarks, it ranks among the top Linux web frameworks in terms of efficiency.

Microsoft’s aspiration to make ASP.NET Core cross-platform led to ASP.NET Core depending on neither the operating system nor the web server which it will run on. ASP .Net Core will run equally well on either Windows, Mac, or Linux, and its projects will be able to run both in Windows Azure Web App or in Docker on Linux, and everything will work correctly in both cases.

Further .NET Core (Roadmap) Development

Nowadays .NET Core is developing actively. .NET Core is adopting more and more common APIs from .NET Framework and Xamarin to make an application portable to all .NET platforms. Microsoft and .NET Foundation are pursuing the following aims in developing upgrades for the framework:

  1. To make .NET appropriate for most of the current development tasks;
  2. To develop high-quality .NET Core versions for Windows, Linux, and MacOS operating systems;
  3. To create high-quality .NET Core versions for processor architectures: x86, x64 arm32, and arm64;
  4. To perform releases of new .NET Core versions at least several times per year;
  5. To allow developers to develop applications as quickly as possible, using intuitive .NET Core tools;
  6. To improve application building productivity in .NET Core to make the development cycle (making changes in code and subsequent code execution on a compiler) as quick as possible;
  7. To improve the work of .NET applications in the cloud – to improve logging algorithms, tracings, and error diagnosis;
  8. To allow the user to assemble .NET Core from source code files independently, including those modified by the user.

The release of the 2.0 version of .NET Core is expected in 3Q 2017. The next version of cross-platform framework by Microsoft is expected to have many improvements. The utility of the second .NET Core version has been proclaimed for the following operating systems:

  • Windows (starting from 7 SP1);
  • Windows Server (starting from 2008 R2 SP1);
  • Red Hat Enterprise Linux (from version 7.3);
  • Fedora (from version 25);
  • Debian (from version 8.7);
  • Ubuntu (from version 14.04);
  • OpenSuse (starting from version 42.2);
  • Tizen (from version 4);
  • MacOs X (from version 10.12).

Microsoft continues to develop other .NET tools, together with .NET Core. These are: ASP.NET, .NET Framework, programming languages for .NET, and others. The project .NET Standard, developed from Unified BCL, is developing actively. .NET Standard is a set of common specifications for all .NET platforms: .NET Core, .NET Framework, Mono, Xamarin, and others. .NET Standard guarantees the usage of its libraries in all .NET runtime environments.

Summary

The contribution of Microsoft to the progress of development tools is, of course, wonderful, but at the same time, the progress of these tools was ambiguous. The tendency to use a huge number of different technologies and approaches to software development resulted in many incompatible languages and development tools. This led to the problem of unification and compatibility of all languages, development tools and technologies ever developed by Microsoft.

Microsoft, having resolved this issue once and having created .NET Framework, faced the problem again. Now this issue presents as different verticals of .NET subsettings, which have originated from one framework but are different, and have become more and more distant from each other as they developed. The colossal effort of developers was needed to create a single software platform. The result of such work was .NET Core – one framework for all .NET verticals.

.NET Core is not just another .NET Framework. As opposed to .NET Framework, it is an absolutely new .NET platform with technologies and work principles entirely different from .NET. Absolutely everything has changed in .NET Core: the framework and its core building principles, the distribution and upgrade scheme (NuGet), development frameworks (Visual Studio 2015/2017 and Visual Studio Code), web development platforms (Asp.NET Core), and even the compiler *(Roslyn). However, Microsoft and .NET Foundation have not hurried to switch fully to .NET Core; they are developing it along with other .NET platforms.

Microsoft Roslyn – using the compiler as a service

.NET Compiler Platform from A to Z

One could encounter different situations where it becomes necessary to write one’s own code compiler, interpreter or analyzer for a programming language. Creation of compilers and interpreters is believed to be an “aerobatics” in programming, whilst the creation process itself is seen as very complicated and time consuming. However, the .NET platform has had tools existing quite for a long time, which greatly simplify this task.

What we had before Roslyn came

The .NET Framework can compile a source code without Visual Studio installed on the machine. The .NET Framework (starting with version 2.0) includes command line compilers csc.exe and vbc.exe. These compilers can be used to build .NET applications from any text file containing C# or Visual Basic source code. The compilers are run from the command line. The command line compiler parameters enable you to:

  • Set the name of the compiled file (/out);
  • Collect console applications (/target:exe);
  • Collect applications with graphical interface without using a console (/target:winexe);
  • Collect dynamically linked libraries (/target:library);
  • Add references to external assemblies (/r);
  • Write command-line arguments for the *.rsp file and specify the name of the rsp file as the command-line argument (@file.rsp).

The csc and vbc parameters perfectly handle the task of compiling a source code contained in one file. But MSBuild is used for the more complex tasks of compiling and assembling projects. Moreover, Visual Studio files *.csproj, *.vbproj and *.vcxproj serve as XML codes for MSBuild. Visual Studio uses MSBuild to build projects. In addition, MSBuild can be called from the command line or from a .NET application code via APIs.

It is also possible to generate a low-level MSIL code using System.Reflection.Emit. You can also go for dynamic code generation for .NET programming languages using CodeDOM, and then compile the generated code with the help of code providers (for example, CSharpCodeProvider, which is an add-in over the csc compiler).

All the approaches listed above were being used for code generation before the emergence of the .NET Compiler Platform, better known as Roslyn.

Roslyn is a collection of open-source compilers, code analysis and refactoring tools which work with C# and Visual Basic source codes. This set of compilers and tools can be used to create full-fledged compilers, including, first and foremost, source code analysis tools.

The History of Roslyn

The name “Roslyn”, the new platform for compiling a source code, was first written by Eric Lippert, a former Microsoft employee, when he started to recruit developers for a new project. Lippert named the compiler in honor of Roslyn, a suburb in Washington.

The first version of Roslyn was released in October 2011 as a part of Community Technology Preview (CTP) – an extension for Visual Studio 2010 SP1. The update of CTP in September 2012, despite the large scale, was not very successful. It had the so-called “breaking changes” – changes in Roslyn components, which could potentially crash other components. Besides, not all the features of the CTP APIs were implemented for C# and Visual Basic languages.

At its Build conference in April 2014, Microsoft announced Roslyn as an open source project, and also implemented a way to integrate Roslyn in Visual Studio 2013. Since then, Roslyn has been distributed under the Apache 2.0 license. However, even by then, not all Roslyn features were implemented – there were plans for deployment in C# 6.0 and Visual Basic 14.0.

Starting with 2015 version, Visual Studio uses Roslyn to compile and build its own projects. However, to date, Roslyn only supports two languages – C# and Visual Basic.

In January 2015, Microsoft moved Roslyn source code to GitHub.

Installing Roslyn

To date, Roslyn has remained a part of Visual Studio 2015 and is installed together with it. Roslyn is a part of Visual Studio 2017 as well. It has been released in March 2017.

However, Roslyn is not included in the .NET Framework. Even in the .NET Framework 4.6 version, the traditional csc.exe and vbc.exe compilers are included. This is done for it to be compatible with previous .NET Framework versions.

To install Roslyn compilers without installing Visual Studio, you need to download and install Microsoft Build Tools. Roslyn can also be downloaded from Github, then you can compile and get binary files csc.exe and vbc.exe, which can be accessed from the command line.

APIs for Roslyn compilers

Most of the existing traditional compilers come as “black boxes”, which “magically” convert the source code into an executable file or library. Unlike them, Roslyn allows you to access each stage of the code compilation and application creation process via its own APIs.

Together with compilers, other “black boxes” are often supplied – integrated development environments (IDEs) that can enable you to increase the development speed with convenient tools, such as code highlighting, Intellisense, refactoring tools, performance analysis tools (profilers) and other complex tools. Roslyn takes over these features and also provides an API to them. Moreover, with Roslyn, the developer can work with the compiler from his own application, using the compiler as a service to:

  • Generate code in C# and Visual Basic (like CodeDOM);
  • Analyze code;
  • Refactor code;
  • Use C# and Visual Basic as script languages, interpreting instead of compiling the code. Roslyn APIs are represented by three sets (Figure 1).
Fig. 1 – Roslyn APIs

The compiler APIs allow you to get an object model of processes that occur at each stage of the compilation process, regardless of the Visual Studio components installed (Figure 2).

Fig. 2. Compiler APIs

The Roslyn compiler pipeline is represented by four phases, each of which has its own object representation:

  1. The parser displays information in the form of a syntax tree;
  2. The symbol declaration phase displays a hierarchical symbol table;
  3. The binding phase returns information in the form of semantic analysis results;
  4. The emitting phase provides APIs for generating low-level code in MSIL language (similar to what System.Reflection.Emit does).

Language services use these APIs to perform their own functions. For example, code highlighting uses a syntax tree, while an object browser uses a hierarchical symbol table.

Roslyn diagnostic APIs allow you to handle errors and warnings that occur at all the compilation stages. Roslyn also allows you to process errors through analysis tools written by the user.

Scripting APIs allow executing C# or Visual Basic code without compilation – something similar to the REPL interactive environment in Perl, Python, Haskell, Erlang, and others.

Workspace APIs gives direct access to the application’s object model in the compiler without parsing the source code files for the second time. The APIs also allow for projects tuning, management of project dependencies, source code generation without using Visual Studio components.

Syntax trees

The syntax tree is the basic structure used by Roslyn for compilation, code analysis, binding, refactoring, code generation and other operations. Roslyn syntax trees have three key properties:

  1. They contain all the source information, such as grammatical constructs, tokens, directives, comments and even whitespaces – all this information is contained in the syntax tree;
  2. The syntax tree or its part can be converted back to the source code – you can build syntax trees and generate code from them, you can edit the syntax tree and it will generate a corrected code;
  3. They are thread-safe and protected from changes. This means that you will not be able to directly change the data in the syntax tree. The tree completely reflects the state of the source code at the time of construction.

These three important attributes of the trees allow you to work with the syntactic structure of the source code, including in custom projects, accessing it through APIs. These properties have also greatly simplified complex refactoring operations, and this happens naturally without direct code editing but only by editing the syntax tree. Each syntax tree consists of the following elements:

  • Syntax Nodes – they represent complex syntactic constructs, such as declarations or expressions;
  • Syntax Tokens – they represent the simplest constructs for constructing syntax nodes. Syntax tokens consist of, for example, an identifier or operator;
  • Syntax Trivia – it represents parts of the source text that are mainly insignificant for the compiler, such as comments, directives or whitespace;
  • Spans display positions within the source text of each node, token or trivia, and its length;
  • Kinds identify the syntax unit in the tree;
  • Errors are processed in the syntax tree in two ways: either by inserting the expected token, or by adding a token that is unknown to the compiler as a trivia.

Semantic model and Workspace APIs

Unlike syntax trees that represent the structure of source code, semantics is the logic in the source code and all its constructs. It includes declarations of variables, classes, objects, fields, methods, function calls and passing parameters to them, types of operands and operation results, and operator priorities. Semantic analysis of source code checks the code (or syntax tree in Roslyn) for compliance with the rules of the language. Semantic model provides the following information about the source code:

  • Semantic symbols: source elements or elements imported from libraries (types, methods, properties, fields, events, etc.);
  • Resulting type of expression;
  • Diagnostic data: errors, warnings, exceptions, etc.

Workspace APIs represent the object model of solutions, projects in solutions and documents in projects. All the objects and methods listed above can be called from any .NET application working with Roslyn as a service and using Roslyn APIs.

Working with Roslyn: samples

There are so many examples of working with Roslyn. Here are some of them:

Future development of Roslyn

Roslyn will be developed further in two important areas: creation of new features and improving existing algorithms. The following are expected among the qualitative improvements of algorithms:

  • Increasing the performance and speed of algorithms in the compiler platform;
  • Creating a new implementation of PDB Writer with big parallelism when writing text to a PDB file;
  • Increasing the test coverage with the help of new testing tools;
  • Eliminating Roslyn’s dependence on the full version of .NET Framework so that Roslyn could be deployed, for example, on WinRT.

Some of the features of Roslyn compilers are still considered experimental and are being tested publicly. Others that have already been implemented can be improved – performance, speed and quality of work can be enhanced. Still others associated with the new functionality require a decision by Microsoft and the .NET Foundation community to be taken first before intensive development and implementation could start. Here are some of the ways to improve the following versions of Roslyn compilers:

  1. New features for programming languages ​​C# 6.0 and Visual Basic 14.0 (more);
  2. APIs for creating XML documentation from code comments;
  3. Improvement of diagnostic APIs for synchronous code analysis in the process of writing it. For example – identifying and indicating errors and warnings while writing code without running it for compilation;
  4. Increasing the performance of code analyzers via Roslyn APIs;
  5. Increasing the number of rules for static code analysis tool FxCop;
  6. Creating APIs for writing custom static code analyzers;
  7. Modifying the semantics of some expressions for scripting languages ​​(C# Script and VB Script);
  8. Improving REPL interface – interactive environment windows for programming within command line interface tools;
  9. Improving APIs for working with scripting languages ​​(C# Script and VB Script);
  10. Increasing the performance of FindAllReferences operation;
  11. Improving the algorithms for finding conflicts when renaming.

Some more piece about Roslyn

Despite the large number of flaws, the Microsoft’s new compiler platform Roslyn is gaining popularity, and it’s no accident. Roslyn is one of the few compilers that give you the opportunity to observe all the compilation and assembly stages, access any intermediate results and internal compiler constructs, as well as use various language services of the compiler, refactoring and diagnostics tools. Due to the wide interpretation options inherent in Roslyn, the C# and Visual Basic have become scripting languages. Despite its relatively small history, Roslyn is already being used in large projects, such as IDE Visual Studio 2015, static code analyzer PVS-Studio, and cross-platform framework .NET Core. It is also used as an alternative to script system Windows PowerShell. In the future, the number of such projects will only increase.

Some life hacks on the use of Roslyn

Roslyn provides a huge set of tools for building your own compilers, code analyzers, interpreters and scripting languages. A significant shortcoming of Roslyn is that it only works with two programming languages: C# and Visual Basic. However, Roslyn makes it easier to create your own language on the .NET platform. In this case, you only need to translate the code into C# or Visual Basic, or create a syntax tree, and then use Roslyn compiler APIs to build a full-fledged application on the .NET platform. Another option is to run the generated code for execution (interpretation) as a script. If you need to generate and compile a source code using C# as a scripting language, then the best solution is to use Roslyn compiler APIs. If you do not like the source code analyzers built into Visual Studio, then Roslyn APIs could enable you to create your own. You can even create your own IDE, using the features of this compiler platform and connecting it as a service to your project.

Roslyn is not just another Microsoft compiler – it is an off-the-shelf framework, which you can use to create your own source code tools. Roslyn gives .NET developers many new features. It is a great tool that helps you to write your own compiler, interpreter or analyzer for a programming language. We advise you to study how the compiler works for it would simplify your tasks. We are interested in Roslyn because it can be used to create your own programming language on the .NET platform.

5 Stages of Building a Smart Website

From Strategy to Design

Today, almost every start-up has its own website or landing page. When building a website, we always expect it to please both the users and us, and, most importantly, build customer loyalty and generate income. But is that often the case? No! Most such sites don’t solve business problems; neither do they meet customer needs.

The truth is that to create a smart website, you need to pass through five important stages. And the design is the last of them (how often do companies start with it!). We are going to discuss these five key stages in this article. We’ll ask you some important questions. Try to answer them for yourself.

Why divide the process into stages?

In his book “The Elements of User Experience,” Jesse Garrett describes five stages of user interface design:

  1. Strategy
  2. Scope
  3. Structure
  4. Skeleton
  5. Surface.

The design process starts with the most abstract expressions about the project strategy and ends with very concrete models of the site.

Figure 1. Jesse Garrett’s view of the web development process. Work starts at the lowest stage (strategy) and ends at the surface.

The first thing to do is to categorize your project into one of two groups:

  • Software interface (online stores and service sites);
  • Information space (blogs and news portals).

The questions that we’ll ask at each stage will depend on this categorization.

The development process needs to be divided into stages to clearly distinguish between the responsibilities of different specialists. A UX designer is engaged in the project at the second or third stage, while the company’s head formulates the strategy at the first stage – before the team starts developing the site features.

You can’t start working on a set of features (feedback forms, calculators, shopping cart, comments section, etc.) without first defining the need for them in the strategic planning stage. It’s not possible to develop navigational items, implement module layout on a page, or develop contextual navigation without ready information architecture and an understanding of what content will be posted on the website.

If you’re interested in more, read Don’t Make Me Think. Rules of a User-Friendly Interface

Maslow’s hierarchy and Garrett’s scheme

In his 2012 book “Designing for Emotion,” which was warmly received by professionals, Aarron Walter uses the famous Maslow’s hierarchy to show how to properly set priorities when creating a website design. Maslow’s hierarchy is a simplified visualization of the hierarchy of needs, developed by American psychologist Abraham Maslow in 1943.

Figure 2. Maslow’s classical hierarchy.
Figure 3. How Aarron Walter sees the use of Maslow’s hierarchy of needs for web design.

Despite the fact that Garrett deals with the entire development process, while Walter is solely focused on design, we can see similarities between both approaches in their quest to segment user needs and website objectives.

If you test Garrett’s scheme (Figure 1) on Walter’s hierarchy (Figure 3), it turns out that strategy is the cornerstone of the whole development process – without strategy you can’t start. Here, design is the apex of the hierarchy, which is a logical extension and embodiment of the goals to be achieved by the team in previous stages. Besides, one can’t deny that a well-grounded strategy and the right content requirements are much more important than choosing button colours and font styles.

As you can see, design is just the tip of the iceberg, visible and very important, but it can’t exist without dozens of tons of ice, hidden under a layer of water. Work on the surface level is the very last thing to do because it is subject to results achieved in the previous stages.

If you’re interested in more, read Icons in Design: Nonsense, Necessity, or Decoration?

Stage 1: Strategy

In the first development stage, we need to answer two key questions:

  • What do we want to get out of our site?
  • What do users want to get out of the site?

It is essential here to pay due attention to the formulation of strategies because Garrett’s entire methodology assumes a ripple effect if there is a need for change. This means that wrong decisions at this stage will automatically make all the decisions taken at subsequent stages wrong or disputable.

Figure 4. Ripple effect of making a wrong decision.

Always REMEMBER that the approved objectives of the website should reflect the essence of the company’s business processes. User needs are easier to identify using user persona methodology and target audience segmentation.

What do you want to get out of your site? What do users want to get out of your site? When answers to these two questions are formulated accurately and clearly, then we can move to the next development stage – scope (features and functions of the site).

Stage 2: Scope

If you consider your site as a software interface, then at this stage, you’ll formulate and describe the features and functions, and prepare terms of reference for programmers. If your site is an information portal, then content requirements move to the forefront.

In determining the content requirements, it is necessary to find out the following:

  • What will be the site content: text, video, audio or image?
  • Why does the user need this content?
  • How often will the content be updated?
  • Who will be responsible for hosting, creation and editing?

Here is a good example of poor work on the scoping stage: thousands of business card websites that have a “news” section, but don’t have any useful information to publish or the news section isn’t updated.

This is because the customer just said, “We need a news page,” but didn’t think about what would be posted there, how often, and who would be in charge of it. So that’s why you end up getting sites with empty and useless news pages.

Figure 5. The website of a construction company has on its news page only 4 news items for 3 years.

In describing the functional specifications of a website, the following needs to be clarified:

  • Why should a particular feature be on the site?
  • How will users interact with it?

It’s all so simple: if in the first stage, you’ve found out that users will be visiting your site to watch videos, then it’s time to talk about what kind of videos those will be and who will create them.

If you’re interested in more, read
Part 1. Responsive Web Design Using Breakpoints
Part 2. Responsive Web Design. Mobile Devices

Stage 3: Structure

At the previous stage, we determined what content will be posted on the site, and which features will be offered to users. At the structure development stage, we’ll determine which particular pages will host the content and features.

SEO experts, marketers and editors are fully involved in the structure development stage. Before developing the navigation system, which is the most important part of the site, the number of pages, their type and relative location all need to be defined.

Experts classify information architecture arrangement into four types:

1. Hierarchical structure. Most online stores serve as a classic example. For example, when selecting specific men’s winter boots from a product catalogue, we normally navigate the following pages/categories: “men,” then “shoes,” “winter,” and then we choose a specific model.

Figure 6. Hierarchical structure.

2. Matrix structure. This lets you navigate through multiple axes. A good example is a blog where each post can belong to more than one category at once. For example, a post entitled “Cheap vacation in Bruges” can be posted in such sections as “Belgium,” “Cost saving,” and “New.” Thus, such a post will be seen by several target groups: people who want to know more about Belgium, people who are looking for cheap vacation packages, and people who regularly follow new posts.

Figure 7. Matrix structure.

3. Organic structure, This type has a very narrow range of application. This architecture can be used in entertainment sites or sites where the user is given the freedom to study materials just like when you visit a museum. This structure is suitable when there is no need to guide the visitor through the web pages, and the visitor doesn’t really care what section he is currently in.

Figure 8. Organic structure.

4. Linear structure. This is characteristic for landing pages. Landing pages are created with the involvement of marketing specialists and schemes such as PMHS (Pain, More pain, Hope, Solution) and AIDA (Attention, Interest, Desire, Action), gradually leading the customer to make a purchase or to another target action.

Figure 9. Linear structure.

An example of poor work at the structure stage is the eventual appearance of additional sections on a site, which was originally designed to be a landing site. This means that developers envisaged user behaviour incorrectly, or they don’t know how and what information needs to be placed on the site.

The structure can be designed via two possible approaches:

  • Top-down;
  • Bottom-up.

The top-down approach implies that the objectives of the site and user needs form the basis for selection of a structure, for example, starting from general categories of the online store and ending with pages of specific goods.

The bottom-up approach is based on content analysis and its requirements. First, we look at what kind of content we have available and what we can create in the near future, then we group it and get categories and sections of the site.

Stage 4: Skeleton

The skeleton stage is very similar to the previous stage, where the structure was considered. Here, it’s also all about placement of features and content – not on the site generally, but within a particular page. Once we have compiled a list of elements and text blocks for each page, it’s time to think about how these blocks will be placed.

It is not enough to tell the designer to make the homepage of your site contain a logo, global and local navigation, breadcrumbs, search, banner ads, and text. We also need to inform the designer how these elements should be arranged relative to each other.

Figure 10. Working on the skeleton stage – page prototype.

Navigation is the main aspect of work at this stage. When arranging elements, it is important to pay attention to how the user will navigate the page.

The main rule: the navigation system must allow the user to easily navigate the site, and it must reflect the interrelationship between pages and interrelationship between a page and the navigation system itself. Simply put, navigation should answer the following user questions:

  • Where am I now?
  • How do I get to where I want?

Prototypes can have different levels of detail, depending on the complexity of the project. A page prototype gathers all layout solutions into a single document, which serves as a bridge between the earlier stages and the visual design of the site.

If you’re interested in more, read How To Create Masonry And CSS Hybrid Grid Layout

Stage 5: Surface (Design)

Now it’s time to figure out what is design and how it depends on the other previous web development stages. All the work carried out at the previous stages (strategy, scope, structure, and skeleton) consists of a formulation of constraints that will be transferred to the designer in the form of input data, requirements and wishes.

These constraints are precisely what allows the designer to do his job efficiently. It enables your website design to meet its objectives. Experienced designers, with one voice, say: “A good design is born only from constraints.”

Experts say that the best design samples emerge from stringent requirements and constraints. A designer who is given a specific field for creativity will create a really nice design, while a designer who is asked to do “something very nice” without constraints will end up doing something that is not effective, even for a huge fee.

You can create the best design for the website of an online store (e.g. selling woollen socks) featuring a shopping cart, blog, material and colour filters, and weekly updated foot-care articles, made in corporate colours. The design can show your company’s logo as effectively as possible. But you can’t create or even imagine the best website design without stringent requirements. After all, these constraints will at the same time serve as evaluation criteria.

It is for the sake of gathering requirements and constraints before rendering the layout that the web development process should be divided into five stages.

Let’s summarize

If you decide to use this web development technique, you must remember that you can’t move on to the next stage until the previous one has been completed. Each development stage – from strategy to skeleton – formulates constraints and input data for a web designer at the surface stage.

Such an approach allows a team leader to narrow down and articulate tasks for each specialist involved in the development process, and secure a result that brings the company closer to having a well-functioning site. If a single web designer is developing the site, this approach would enable him to create a fully-fledged site on his own, giving adequate consideration not only to the layout but also to customer needs.

So, design is simply a visualization of solutions within the framework of elements of user experience (adopted during the development process) in the first four stages. If the strategic objective of your site is to generate profit, if the user needs to buy woollen socks, then a good design should help you sell a lot of socks at a price favorable to you and reasonable for customers.

Lean Software Development Using the React Ecosystem

Choosing the Right JavaScript Framework

In this article we’ll elaborate on how we use React and the ecosystem around it to enable lean software development. Several options for frontend development are presented. When there is need for a web app framework, businesses usually choose between Angular, Ember and React.

React

The decision to choose any of these frameworks is usually driven by a simple question: how easy would it be to hire a dedicated team and later gather the maintenance and support team. By easy staffing, we mean the availability and cost of developers.

Cost and availability are the reasons why non-mainstream frameworks are not even considered for a job.

Aurelia, Vue, Polymer and many other frameworks provide great technical ideas and they are good for special cases. However, these frameworks may lead to excessive costs if selected as a base for business. This is because there is shortage of readily available and qualified developers to do the job using these frameworks.

The use of one of the mainstream frameworks will enable businesses to control costs and manage projects predictably.

Why React?

There is no silver bullet or framework to solve all issues. Apart from technology, many other things should be agreed upon and communicated during a project.

From the prototype to design and implementation, product development requires the use of specialized tools at each production stage. These tools are usually not integrated. There is a person in between, who transforms the output from one tool to an artifact that is useful during later stages. An example is a UX researcher that gives the designs to a frontend engineer, who then manually transforms them into code. This process generates waste and slows down iterations, which is not lean.

Let’s assume that a proof of a concept confirmed our ability to implement some technology. A standard loop for creation of wireframe, prototyping, UX, design, and development should be iterated until there is confidence that MVP is ready for production.

This is the greatest discriminator of the project path that we are about to travel. Depending on team capabilities and the certainty in the path to be executed, we should make our choice from any point between two polar options:

  1. Employ a multi-talented team, where the product owner, UX researchers and designers would draw sketches, wireframes and interactive prototypes which are then handed over to the development team for implementation in a selected technological stack;
  2. Allow the product owner to iterate with the development team directly, while feedback on an artifact from one iteration is a direct input for the next one.

Option A is recommended when the product owner is certain on what is needed as the end result. This is usually the case for a business that is making an investment and the resulting product is expected to be an integral part of an existing system.

Option B would be more desirable for innovative products, startups, and research projects. This is because it allows for very rapid change in development direction while preserving speed. This is possible thanks to the application of lean software development principles and practices which could be enabled by a unified toolset built around a common framework.

React and the ecosystem around it are always in flux, but they are mature enough to cover a full cycle from the prototype to MVP and to production deployment both for web and mobile applications and soon for virtual reality apps.

There is no need to produce wasteful deliverables outside of the React ecosystem. Proof of concept, wireframes, interactive prototypes and MVP could be built from one another on each consecutive iteration. By reusing code between production stages, waste is eliminated and learning amplified.

Each team member could see the whole since the common stack is used throughout the project. It is all React and JavaScript. This helps them to build in integrity since they could refactor parts of a system as new feedback is collected.

Lean Toolset

Convention

The first thing to do on a new project is leveling the ground. Project time shouldn’t be spent on selecting tools, integrating them to work smoothly together and teaching team members to embrace them.

This is why tools should be ready, team members should have the skills and use these skills properly, and convention should be established by a lead. A convention over configuration approach increases certainty. This allows developers to think more about the product instead of arguing about non-significant details. These details should be resolved in advance. For this reason, tools are collected and integrated in a toolset.

Lean Toolset: create-react-app

create-react-app is a React project generator and toolset which allows bootstrapping a React project without configuring the build tools in advance. The convention over configuration approach used by the create-react-app saves time in most cases, while for advanced cases, it is not limiting.

When advanced setup is needed, we eject configuration using built-in react-scripts and extend it accordingly. However, the rule of thumb is to work with the idiomatic create-react-app since it simplifies the overall system and imposes best practices.

Lean Toolset: redux and common packages

create-react-app is good for bootstrapping, but not suitable for application development.

We always add redux for state management and react-router for routing to our applications. Other than simplifying state management and routing, those commonly known packages bring design patterns which would simplify application testing, allow code reuse and portability between different use cases and platforms.

Lean Toolset: Material-UI

React itself is a major enabler. Applications built on React and redux are composed of components with clear state and lifecycle management. They have capabilities which allow us to change composition, behavior and business rules on the fly, without breaking other parts.

Material UI

All of these technical capabilities should be accompanied by a solid UI kit, so the system has the look and feel of an integral whole by the customer. We selected Material-UI from a set of readily available UI kits to unify complex interfaces since it integrates with the create-react-app easily and can be customized.

Material-UI is a readily available UI kit that follows Google’s Material design guidelines. It allows for the quick creation of interactive prototypes. The look and feel are customizable, which is only needed in the later stages. For prototypes, we recommend focusing on user flows.

Lean Toolset: Storybook

Storybook is a tool for creating a living style guide comprising of React components. This means that at any point in time, you can change your components and immediately see how they look, feel and behave in different states. This shortens the feedback loop after each change and makes everyone confident that no look and feel regression was made.

Story Book

In addition to the usual benefits that a living style guide brings, Storybook enforces some useful design patterns, such as differentiation of container and presentational components.

The storybook is composed of presentational components that are shown in different states. Container components, which map presentational components to the rest of the application, are not needed and are not welcomed by a storybook. Therefore, we are forced to separate containers from presentational components.

The separation of concerns principle allows us to decide as late as possible and make architectural decisions on component interconnections, only when uncertainty is eliminated.

With Storybook, we could deliver the interactive look and feel as fast as possible.

Lean Toolset: Jest

While Storybook allows building confidence in the look and feel visually, automated testing empowers every team member to make bold changes with the assurance that no regression is introduced.

Unit Testing with Jest

There is a long list of benefits of automated testing. The key advantage here is the ability to build a robust continuous integration and delivery pipeline which allows fast and iterative delivery.

We selected Jest as a base tool because of its tight integration with React. The developer experience of testing JavaScript code with Jest is excellent. It enables rapid development by running only specific tests just in time when changes are made to units under test.

Pragmatic Development

There is considerable uncertainty in software development. That uncertainty should not block product development. The tools presented empower our team to deliver the known parts fast and to highlight the unknowns. This allows stakeholders to see and act on them early.

Don’t Make Me Think

Usability consultant and information architect Steve Krug has been in the usability art since 1989. He has years of experience as a user advocate for major companies as Apple, AOL, and Netscape. On the question of what’s the most important thing to do to make sure a site or app is user-friendly, he answered that it’s not “Nothing important should ever be more than two clicks away” but rather “Don’t make me think” – his first law of usability. This advice is also the name of Steve’s most famous book dedicated to user interfaces.

Steve Krug’s special gift is in his constantly fresh look and the ability to put into practice the experience he acquires from studying human behavior on the Internet. At the beginning of his professional career, Steve would look at the designer’s computer screen over their head while they are working, thus preventing them from being excessively fond of visual ideas that could throw ordinary users into confusion.

Krug’s technique was not to conduct experiments on focus groups, but to study the behavior of ordinary people when using websites.

In this article, I’ll talk about the main empirical observations that Steve formulated in his book, complementing them with my own experiences and opinions of designers who I know. I’ll begin by describing the general principles and problems and then move on to an analysis of particular mistakes, then I’ll give useful tips.

How the user defines simplicity

When assessing something, we use our experience and various coordinate systems. If you ask someone to assess a car, he will pay attention to the speed and driving. When selecting a house, we are likely to be most interested in the land size and location.

While appraising the simplicity of a website, the user will first indicate the time spent on getting what he wants from that site. If it takes a user more than five minutes to order a pizza on your website, then your interface has some problems.

First of all, don’t make the user do what you could do for him. Features such as geolocation, autocomplete forms and authorization via social networks instead of registration form simplify any interface significantly.

The designer is the one that thinks, while the user uses. Another factor that plays a role when assessing a website is the simplicity of thought processes. If you want to obtain the user’s phone number, then don’t make him ponder on which format to enter the number.

Anything we’re used to seems simple. Avoid being too different from competitors. If you’re a sushi seller, just make very delicious sushi – the customer has ordered for them a hundred times in the past and his brain has already developed a particular scenario. Any deviation from the usual scenario has to be reasoned: if your interface throws out the user, he will order the sushi only if they are much cheaper. Otherwise, he’ll return to that site where he has ordered for sushi many times before.

Below is an example of a site, delivering sushi in London. Why do they need the user’s date of birth? Why do I have to register to eat? Why can’t I log in via social networks?

An example of a site, delivering sushi in London.

In studying a site, the user has to think as follows: &quout;This key is for this, if I click this one I will be able to read about that, I can click here to make a call”. You shouldn’t generate questions in his head. A site is difficult, if by looking at it, the user thinks: &quout;What is this thing for? What happens if I click here? Where is this written about?”. All questions must be answered preventively.

From general to specific

I’ve identified and summarized the most important (in my opinion) principles of creating interfaces from the “Don’t Make Me Think” book. I’ve also tried by myself to deduce some specific rules from the philosophy of this book.

Ports of entry

Brion Gysin:
– How do you… How do you get into these paintings?
William Burroughs:
– Usually, I get in by a port of entry, as I call it. It is often a face through whose eyes the picture opens into a landscape and I go literally right through that eye into that landscape. Sometimes it is rather like an archway. … Any number of little details or a special spot of color makes the port of entry and then the entire picture will suddenly become a three-dimensional frieze in a plaster or jade or some other precious material.
The Beat Hotel by Barry Miles

You started to read this article from the heading, which is its point of entry. In studying an interface, the user looks for something from where to start. It is the designer’s task to make the entry point clear. Without the heading, you would not understand what the article is all about before starting to read.

Targeted action is a process consisting of several steps. If you don’t show the user where to start, he most likely will not ever start. Imagine a website of a manufacturer of computer components. For a user who wants to download a motherboard driver, the point of entry must be an element directing the user to the first step of the following process:

1. Selecting or searching for a device;

2. Selecting an operating system version;

3. “Download” button.

You shouldn’t create a page that performs several targeted actions, else it would have to host multiple entry points, which could confuse the user.

Lao Tzu once said that a journey of a thousand miles begins with a single step. But this step – no matter how important it may be – is not the entire journey. When asked about how many moves ahead he is planning, Garry Kasparov answered: “In chess, it is far more important not to calculate dozens of moves ahead, but to have a clear understanding of the situation on the board at that moment”.

Besides, to show the user the way, you have to accompany him along that way so that he doesn’t stray away. In constructing a route, nothing helps as knowing one’s location. A breadcrumb trail does an excellent job in helping users keep track of their locations within programs or website.

Users will not use a site if the navigation isn’t clear.

You can’t write art

Copywriters say that writing texts for a robust interface is an art, but not writing them at all is an even bigger art. Steve Krug says, “Get rid of half the words on each page, then get rid of half of what’s left”.

In the The Elements of Style by Elwyn Brooks White and William Strunk Jr., rule number 17 reads:

“Vigorous writing is concise. A sentence should contain no unnecessary words, a paragraph no unnecessary sentences, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts”.

Most words on any web page just take up space. Removing unnecessary words has three aims:

  1. Reduces noise on the page;
  2. The user’s attention is focused on the remaining words, which make up the truly useful and important content;
  3. Reduces the size of the page, and the user can easily sweep his eyes over it in search of the necessary information.

All sorts of “Welcome to the site…” and “The site has a lot of very interesting things about…” should be removed ruthlessly. Users want to go straight to the point – all kinds of introductions only distract attention and waste time.

If you want to ask the user to fill out a form, instead of unnecessarily telling the user that the form would help improve the service, tell him that it won’t take him more than three minutes to fill the form.

What’s this button for?

Imagine that you visited a friend at his house, took the TV remote, and instead of turning down the sound, you mistakenly changed the channel because the volume buttons are identical to the switchover buttons. This is a clear example where the designer had not thought and made the user to sort out the interface by himself.

Inscribing a text on the button is, of course, the best tool that would explain to the user the function of that button. If this button is used to add an item to the shopping cart, then the phrase “Add to cart” or “To Cart” should be written on it. An experimental “Wishlist” or incomplete and indistinct “Add” will raise questions and make the user lose confidence. Another important rule: verbs on the buttons should always be in an infinitive form so that the user can quickly perceive their functions.

The user should clearly know what’s going to happen once he clicks the button. But that’s not even enough – clicking should give him exactly what he expects.

Harm caused by guidelines

The main sin committed by all guidelines present in any interface is that they shift mental work from the designer to the user. Besides, the presence of guidelines on an interface is often a sign of inefficiency by the designer.

Nobody is going to spend his time reading guidelines present on a site until several attempts to use the site, as it turns out, fails.

Even if the user needed to read the guidelines, he would unlikely do so if it is too cumbersome. In designing an interface, it is the designer’s task to remove any guidelines – all elements and user scenarios should be self-explanatory. If guidelines are really needed, they should be very brief.

Coincidence of interests

That which you want to show a user on a particular page must match with what the user is looking for on that page. Then the design will look simple and clear.

Let’s assume that people buy dishes and other kitchen utensils more and more often than construction tools and repair materials. This doesn’t mean that you should go hang the sign “Dishes at wholesale prices” at the entrance to your hardware store with the hope of attracting buyers.

Firstly, you will not get an inflow of the target audience to your store, and secondly, people will be deceived, which is not good. The same logic should be applied when creating the structure of a website. If your company deals in the repair and sale of computer hardware, share not only the target audience but also the sections of the site.

Don’t try to squeeze everything on a single page (cramming the description of repair services and the product catalog all in one page), else you might confuse potential customers.

Most burning issues of the day

In this article, I’ve shown that every designer can greatly simplify the lives of users through simple reflections. Let’s look at some examples of how this could be implemented on large and well-known websites.

On the FAQs page of the AT&T site, questions and answers are presented in the form of a fashionable accordion. This idea is very good if the concealed information is so large that it will be reasonable not to show everything at once, in order to make things simpler for the user to search for the appropriate question. But here we see that the answers are short and thus could be presented at once without any consequences. The designer should have thought about this and not make the user click on the plus sign.

Page with answers to frequently asked questions on the AT&T website.

On the Coca-Cola website, you can order a bottle bearing your own name or any inscription. After entering the name you want, you need to click on the “Preview” button. Oh, how nice it would have been without this button. They could, in fact, show the inscription on the bottle at once thus saving a click.

From Coca-Cola site. The user could do without the “Preview” button.

Another example: the screenshot of a site offering tours across China. The phone number is shown as an image, which is a link to the contact page. Why not just make it a text, and in addition – a link that enables the user to (by a click) call from his smartphone?

Screenshot of the site www.chinatravel.com

Ok, that’s enough of negative examples. Let me highlight a nice feature in the official online store of auto racing Formula 1. When you go to the checkout page, in the “Destination Country” field, the system automatically detects the user’s location. This is very nice. Keep it up!

Screenshot of the official online store of Formula 1.

Conclusion

“One man likes to push a plow. The other likes to chase a cow. But that’s no reason why they can’t be friends” – Broadway musical “Oklahoma” by Oscar Hammerstein.

The same questions constantly cause irreconcilable arguments and almost religious differences among web developers. In such disputes, you can rarely impose your views on the opponent. On the basis of what web developers do, they have very different views on the same issues.

I want to say that questions such as “Do users like a drop-down menu?” are detached from reality and don’t make any sense at all. Answers to them have no practical application. It is by far more productive and correct to state the question as follows: “Does this particular group of users like this particular drop-down menu on this particular site?”.

Endless arguments yield no result, but only waste your precious time. It’s more effective to test solutions in specific situations. All web development-related issues should be transferred from the “right or wrong” and “like or dislike” planes to the “working or not working” plane.

How To Create Masonry And CSS Hybrid Grid Layout

Today’s web design world has become so innovative. Table-based lists with offset pagination are rapidly falling out of favor, while masonry layouts with infinite scroll are now becoming the new trend. You are not aware of it yet? Think Pinterest, Interview Magazine, Windows’ Metro etc. To describe it in words, it’s an almost crazy paving effect whereby variable sized blocks of content are pieced together in an aesthetically pleasing style and often staggered. Masonry style layouts aren’t something new.

How To Create Masonry And CSS Hybrid Grid Layout

So why look at them now? After all there are some great solutions out there that can give you a masonry effect. This is true. However, can we push a pure CSS solution a little further? Can we leverage Flexbox to achieve a more desired effect and push the capabilities a little further?

Well, in this article, we try to provide an in-depth look at masonry layout and its main perks of usage.

Default Situation

Everyone knows that if you want to display a grid of elements (announcement of blog posts, online store goods, galleries, etc.), you’ll face floating and alignment problems where the height of blocks is unspecified.

E.g., indicating the float:left property – even with the same width for all blocks – would lead to the following mess:

How To Create Masonry And CSS Hybrid Grid Layout
Pic. 1 – Default alignment.

Another option is more pleasant to the eye – when the blocks are arranged line-by-line on a vertical grid (frequently used for the goods catalog) or masonry grid with vertical customization of blocks (used for blogs).

How To Create Masonry And CSS Hybrid Grid Layout
Pic. 2 – Line-by-line block layout.
How To Create Masonry And CSS Hybrid Grid Layout
Pic. 3 – Masonry layout.

Responsive grid with line-by-line display of blocks of different heights

Well, it may seem that everything is obvious here. But it isn’t.

Let’s assume we have blocks of the same width, displayed on a 4-column grid and have the float:left property. After every 4th block (the last in line), we use the clear:left property or display each line as a separate block. But for a responsive layout, it’s a doubtful decision to make block-lines with block-columns inside because the layout will be reconstructed and the number of columns will be changed. Moreover, one should be careful when clearing context due to column variability.

How To Create Masonry And CSS Hybrid Grid Layout

Therefore, we proceed as follows. Let’s take a sample layout in which we need to display a maximum of 6 columns and a minimum of one. First, we should ensure that starting from the 7th element, every 6th element is displayed from a new line. Then, due to narrowing of the display area, the rule should be dropped, while another one adopted – every 5th element starting from the 6th one will be placed on a new line and so on, till the layout takes a one-column form.

In the article Responsive Web Design Using Breakpoints, we mostly focused on the principle on which properties of screen size ranges are overlapped. And this is precisely the case when it’s really convenient to use media-queries like “from and to” with properties applied to the strictly specific range.

Before writing the code, let’s denote ranges:

  1. Everything that is more than 1600 pixels – 6 columns.
  2. 1400-1600 – 5 columns.
  3. 1400-1200 – 4 columns.
  4. 1200-900 – 3 columns.
  5. 900-600 – 2 columns.
  6. Less than 600 – 1 column.

When we transform it into CSS, it will look like this:

.element {
float: left;
padding: 0 15px;
margin: 15px 0
}

For definition above 1600 pixels, we need to set a value such that each 6th element starting from number 7 is placed on a new line.

@media screen and (min-width: 1600px) {
.column:nth-child(6n+7) {
clear: left
}
.column {
width: 16.666%
}
}

Our new command works similar to the range of 1400-1600 where every 5th element starting from number 6 is placed on a new line, and so on in descending order.

@media screen and (min-width: 1400px) and (max-width: 1600px) {
.column:nth-child(5n+6) {
clear: left
}
.column {
width: 20%
}
}

Well, the result is as follows:

How To Create Masonry And CSS Hybrid Grid Layout
Pic. 4 – clear:left on every 4th element, starting from the 5th one, we get a four-column grid. The red frame is the border column; the gray color fill is an imitation of the content with unspecified height..

Source 1

At the above layout, we see that the height of the column cells is equal to the height of the content. If you want the height of the columns to be the same (equal to the largest column) in one line, then all you need to do is to indicate the following for the wrap block:

.wrap {
width: 100%;
display: -webkit-flex;
display: -ms-flexbox;;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap
}

Pseudo-classes: nth-child, mentioned above would be unnecessary in this case (see Source 2).

But this is not quite our topic for discussion because we are most interested in display of brick blocks of different heights (pic.3).

If we want the vertical distances between blocks to be equal, we should use jquery plug-ins instead of css.

Jquery plugins for masonry layouts

There are so many different jquery plugins. They have been there for a long time and have been generally performing well. Masonry, Isotope & Freetile are among the most well-known plugins. Historically, the first and foremost duty of these plugins has been to create galleries. Some of them still don’t go beyond this role, while some acquire more optional features (sorting, animations). If you have a gallery and variegated images by size, then this is the perfect solution you’re looking for. As a rule, it is enough to add a class either to a parent block or to the elements located inside it and then launch the plug-in.

How To Create Masonry And CSS Hybrid Grid Layout

But we are mostly interested in displaying grid tiles of both text and images. Well, yes, they allow to do this indeed, but there is one catch…

At least, all the plugins known to the author are based on the same principle:

With Javascript, a new absolute positioning is set for the elements and coordinates are recalculated. As a result, each of them is assigned with the properties left and top in pixels. When you change the size of the browser window, the absolute values are recalculated.

Although these plugins are of high quality but they sometimes witness some failures in their operations.

1st case: sometimes blocks are placed end-to-end to each other without any margins (probably because the plugin has been triggered just right before all the necessary elements were loaded for correct calculation of position). To overcome this, you can activate plug-in initialization once again after the document has been fully loaded:

$(window).bind("load", function() {
YourPlugInStart();
});

where pluginStart is the function of plug-in launch.

The second detected trouble stems from the fact that since system resources (all operations occur in the RAM) are required for constant rearrangement of blocks and recalculation of coordinates, the site may hang with high data sufficiency. This almost never happens with desktop versions, but there’s a great chance that it may happen when the site is displayed on an iPhone. Especially if the plugin uses different effects of movement visualizing and block emergence.

Therefore we decided to follow a fundamentally different approach. Although this way is not a universal one but it is less resource-intensive and lightweight in which a simple grid and masonry will be combined. Consequently, positioning issues will be solved by means of CSS instead of JS, which will give additional flexibility to our plugin.

Masonry & Grid Hybrid

As you can see from the title of the chapter, we’ve decided to combine the grid structure of adaptive layout to solve the problems connected with positioning by means of CSS. We’ve also made blocks vertical without changing their coordinates, but placing them in the columns of our layout by using JS.

a) Run

The source code of plugin & sample. Demo.

<link href="anotherbrick.css" rel="stylesheet" type="text/css"/>
<script src="anotherbrick.js"></script>

As in the case with the above-mentioned plugins, we’ve placed tile blocks inside the wrapping block. The parent block is given the the-wall class. Elements which will be further aligned are given another-brick class.

<div class="the-wall">
<div class="another-brick">...</div>
<div class="another-brick">...</div>
...
<div class="another-brick">...</div>
</div>

Initialize

AnotherBrick();

b) Operation principle of the plugin & its main perks

After launching JS, the responsive grid is formed with empty columns.

Depending on the width of the display area, the number of columns varies from 12 to 1 by means of CSS (this can be changed. If you have such a need, please, see source).

The borders for transition to a different column number can be changed in the plugin file anotherbrick.css. The whole logic here is:

  • For windows with 2900 pixels, it will be 12 columns (100%: 12 = 8.3333%).@media screen and (min-width: 2900px) {
    .brick-col {
    width: 8.3333%
    }
    }
  • If the area is less than 2900 pixels, then we already have 100%: 11 = 9.09% and then the column number 12 should be disabled..brick-col {
    width: 9.09%
    }
    .brick-col:nth-child(12) {
    display: none
    }
  • If the area is less than 2600, similarly, we should define a new column width and remove the column 11..brick-col {
    width: 10%
    }
    .brick-col:nth-child(11) {
    display: none
    }

    And etc. (please, see css-file).

Therefore, we have fully imposed the task of mutual positioning of blocks on css, which means that no calculation of positions of elements is done and extra cpu resources are not used.

How To Create Masonry And CSS Hybrid Grid Layout

We have a grid of empty columns, but we should enter the content in it. Then the plug-in sorts a list of elements alternately arranging them in columns based on the principle: the 1st element in the 1st column, the 2nd element in the 2nd column, etc. When the plug-in reaches the last column, it keeps on filling the elements starting with the 1st again.

But one should keep in mind that the number of columns varies. Therefore, the plugin monitors the situation and as soon as there is transition from one number of columns to another, it rearranges the content in columns.

But one should keep in mind that the number of columns varies. Therefore, the plugin monitors the situation and as soon as there is transition from one number of columns to another, it rearranges the content in columns.

AnotherBrick(N);

where N stands for the number of columns

Summary

Well, our plugin really has no weak point, but rather a technical feature. Due to its focus on the grid structure of layout, it cannot be used for tasks where “bricks” have different width and the layout has no grid.

How To Create Masonry And CSS Hybrid Grid Layout

Questions of this kind are solved using “classic” masonry-plugins. Also one should be realistic: our plugin have no tile customization mechanism with a priority to fill the space as uniformly as possible. It just sorts them (tiles) out by columns. While masonry, isotop and others customize tiles on the priority of maximum density and sometimes can create more visually balanced layout.

Therefore, it’s better to use them in cases when the height of one block is 600 pixels and another is 100 pixels. If the height of blocks doesn’t vary by more than 3 times and there are more than 20 blocks, then the pattern will be the same in all plugins including ours. Major advantages of Another Brick include the css-mechanics, facility, and ability to adapt to user’s needs.

Moreover, there is a chance that the distribution of blog posts with our plugin will be more readable in terms of chronology. Since masonry plugins are placed close to each other, it often occurs that the dates are a bit mixed.

Part 2. Responsive Web Design. Mobile Devices

We brought up an issue of breakpoints for a desktop/laptop responsive site version in the previous article Responsive Web Design Using Breakpoints. Now it is time to talk about the mobile layout. Let us make two features clear for you to take full advantage of the information below. These features are viewport meta tag settings and the DPI. Though simple at first sight, these things cause much confusion.

Viewport Meta Tag

Let us leave lengthy theorizing aside and go straight to the practice.

Viewport Meta Tag is a command telling to the gadget how to scale the website. We would like to make an honest agreement on not trying to squeeze the mock-up evenly into the screen’s size, making the user’s vision blurry.

Responsive Web Design. Mobile Devices
Pic.1. Viewport is set incorrectly or absent
Responsive Web Design. Mobile Devices
Pic.2. The settings are correct, but styles for mobile devices are absent
Responsive Web Design. Mobile Devices
Pic.3. A fully functional mobile version of a site with correct settings and styles for mobile devices.

Add meta tag with parameters:

<head>
<meta name="viewport" name="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
</head>

Set any width supported by the device, launch the site in a 1:1 scale and forbid further zooming.

What Happens When You Ignore Viewport:

Devices will scale the mock-up at random, leaving you no way to find out, how many pixels are actually displayed in the browser’s window.

DPI

DPI is a quantity of pixels (dots) per inch.

Modern mobile phones and some PCs have the pixels density of over 72. However, we do not believe their producers: they do not tell us the whole truth about coordinates used to display mockups. The mere size of screens in pixels does not say enough to do the math.

The thing is, mobile browsers use their own points, not equal to the physical pixels of a device. Usually these points are divisible by two in order to make information volumes visually comparable, considering the physical dimensions of devices. For instance, 1000 pixels for a smartphone is the size of a palm, 1000 pixels for a PC is the size of an A4 landscape sheet. That is why a mock-up which looks easy-to-eye on PC will look small and unreadable on the display’s screen.

iPhone 6 Example

iPhone 6 is 750 pixels wide. However, the browser divides this value by two and thinks that the full width mock-up has 375 pixels. A 750 pixels-mock-up will be either displayed only in half or squeezed in, depending on viewport settings.

Our honest agreement, however, keeps us from squeezing. It leaves us only displaying the mock-up correctly in 375 pixels, which are the said points in terms of high DPI mobile devices.

2 pixels of the gadget’s screen horizontally equal 1 pixel (point) for browser. The same in vertical direction.

Mobile Device Detection

We remember from the first part to use an abstract styles.css file with all styles and a responsive.css file containing breakpoints and styles for different statuses of the desktop version of a site.

Now we need 2 additional css files, for tabs and for smartphones. The files are added in this order:

  1. styles.css
  2. responsive.css
  3. phone.css or tab.css

To identify device type, use a server-side method: for example, PHP class mobile detect.

<head>
<meta name="viewport" name="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link href="/css/styles.css" rel="stylesheet" type="text/css"/>
<link href="/css/responsive.css" rel="stylesheet" type="text/css"/>
<?php
require_once 'Mobile_Detect.php';
$detect = new 'Mobile_Detect';
if ($detect->isMobile() && !$detect->isTablet()) {
echo '<link href="/css/phone.css" rel="stylesheet" type="text/css">';
}
if ($detect->isTablet()) {
echo '<link href="/css/tab.css" rel="stylesheet" type="text/css">';
}
?>
</head>

All the CSS styles for mobile devices are written in the phone.css and tab.css files; we also include media queries to avoid a pileup of files. The logic of breakpoints activation is the same as for desktop/laptop versions, namely a cascaded inheritance of properties from the largest scale to the smallest one (see Part 1). Sometimes you only need 2 variants of style to be coded, for landscape and for portrait orientation. The minimal width is 320 pixels, while the said iPhone 6 Plus is 414 px wide: that is why some elements need to be adjusted to the size of the browser’s window.

Server Side Vs CSS & JS Detection

Traditionally gadgets have a high dots density, a higher than 1.5 pixel ratio, and smaller screens than desktops. However, technologies change and limits become more and more blurred. Apple laptops and desktops, for one, already got retina displays with a higher dots density. Resolutions of tablets and laptops have been already comparable for a while.

If you do not have a bulletproof solution for CSS-detection you will google to find a great deal of variants. All else being equal, the service-side device detection method is useful for small and medium web projects (see Part 1), as it:

  • works easily and reliably
  • does not require you to make up conditions by searching parameters of devices
  • enables an easy fine-tuning of interface elements and content design

All CSS files can be divided according to purpose:

  1. Common files for the UI and content + desktop/laptop styles (the latter can be made separately or placed into the 2nd file of this list).
  2. File for supporting the desktop version responsiveness.
  3. Mobile devices only.
  4. File containing only css-animations.

The code will be more readable and less cluttered. While tuning your work with separate files, each having a specific function.

Consider animations: they are, including durations and easings, pretty bulky. Being kept in a separate file, they will not interfere with the adjusting of main styles, and in case of doubt you can turn them off until you find the problem.

JavaScript is another method of device detection. However, if you do not want to reinvent the wheel, you have to install an external script or plugin. You will assign class mobile to tag body according to results and build up styles for devices of the .mobile .element { } type without dividing the styles into separate files.

The server-side device detection method has an advantage. It turns a small chunk of your code within the head tag containing conditions for linking style sheets into a somewhat of a headquarter, where tasks are distributed. This way you can enable not only different style sheets, but JavaScript files and chunks of code for specific devices as well.

It is simple and it works. You need less time to do that than you have already spent on reading this article.

More About CSS for Mobile Device

Media queries in CSS for smartphones are set like in the main site version. Don’t be confused that in css pixels are pointed out. This is css notation. The same points are meant here.

@media screen and (max-width: 640px) {
}
@media screen and (max-width: 480px) {
}
@media screen and (max-width: 375px) {
}

Here are some media queries to detect device orientation:

@media screen and (orientation: landscape) {
}
@media screen and (orientation: portrait) {
}

The combinations with coordinates and orientation may also be useful:

@media screen and (orientation: portrait) {
@media screen and (max-width: 1200px) {
}
@media screen and (max-width: 1024px) {
}
}
@media screen and (orientation: portrait) {
@media screen and (max-width: 1024px) {
}
}

Two Lifehacks

Lifehack # 1

iPhone – to prevent shortsightedness, apparently – enlarges fonts it finds too small without asking. To avoid this, write in the file phone.css:

html {
-ms-text-size-adjust: none;
-webkit-text-size-adjust: none;
}

Lifehack # 2

This inappropriate situation makes iPhones and iPads ignore viewport settings, interfering with fine tuning. There is often a bar navigation element with different buttons, fixed in the upper part of your mock-up and having the following properties:

width: 100%;
height: 40px;
position: fixed;
top: 0;
left: 0;
min-width: 990px;
z-index: 10p;

The property min-width: 990px is necessary only for the main version; you do not need it for the mobile one. You expect the element to spread out of screen boundaries, as its minimal width is too big. Far from it! iPhone decides to ignore viewport and forcefully squeezes whole mockup in such a way so that this element can fully fit into a screen so that entire website content badly decreases (see Pic.1). Stay alert and set the minimal width for fixed elements, as sometimes gadgets work against any logic.

Summary

  • Detect device type with the server-side method using php class (you can find similar solutions for other languages).
  • Continue making breakpoints with the size of the browser’s window reducing; the same way as in the main design version (the methods are covered in the previous article). It means your mobile layout inherits properties from the most compact desktop design.
  • Using the methods described for adding the necessary style sheets and scripts for each specific device as your construction kit, you can separate the CSSs of mobile and desktop versions to make them visually independent.
  • Remember to set specific viewport parameters.

It is unlikely that you will need additional media queries detecting retina to optimize graphics. Now all smartphones have a high DPI, so the styles in phone.css are completely suitable for them.

Download source files.

Anna Vasilevskaya
AI modified real photo
Anna Vasilevskaya
Account Executive

Get in touch

Drop us a line about your project at
[email protected] or via the contact
form below, and we will contact you soon.