Quick Links

Letzte Änderungen

    11.1.2019 - Version numbers in .NET Projects

    Any software product should have a version number. This article will answer the following questions about how Encodo works with them.

    • How do we choose a version number?
    • What parts does a version number have?
    • What do these parts mean?
    • How do different stakeholders interpret the number?
    • What conventions exist for choosing numbers?
    • Who chooses and sets these parts?

    Stakeholders

    In decreasing order of expected expertise,

    • Developers: Writes the software; may change version numbers
    • Testers: Tests the software; highly interested in version numbers that make sense
    • End users: Uses the software as a black box

    The intended audience of this document is developers.

    Definitions and Assumptions

    • Build servers, not developer desktops, produce artifacts
    • The source-control system is Git
    • The quino command-line tool is installed on all machines. This tool can read and write version numbers for any .NET solution, regardless of which of the many version-numbering methods a given solution actually uses.
    • A software library is a package or product that has a developer as an end user
    • A breaking change in a software library causes one of the following
      • a build error
      • an API to behave differently in a way that cannot be justified as a bug fix

    Semantic versions

    Encodo uses semantic versions. This scheme has a strict ordering that allows you to determine which version is "newer". It indicates pre-releases (e.g. alphas, betas, rcs) with a "minus", as shown below.

    Version numbers come in two flavors:

    • Official releases: [Major].[Minor].[Patch].[Build]
    • Pre-releases: [Major].[Minor].[Patch]-[Label][Build]

    See Microsoft's NuGet Package Version Reference for more information.

    Examples

    • 0.9.0-alpha34: A pre-release of 0.9.0
    • 0.9.0-beta48: A pre-release of 0.9.0
    • 0.9.0.67: An official release of 0.9.0
    • 1.0.0-rc512: A pre-release of 1.0.0
    • 1.0.0.523: An official release of 1.0.0

    The numbers are strictly ordered. The first three parts indicate the "main" version. The final part counts strictly upward.

    Parts

    The following list describes each of the parts and explains what to expect when it changes.

    Build

    • Identifies the build task that produced the artifact
    • Strictly increasing

    Label

    • An arbitrary designation for the "type" of pre-release

    Patch

    • Introduces bug fixes but no features or API changes
    • May introduce obsolete members
    • May not introduce breaking changes

    This part is also known as "Maintenance" (see Software versioning on Wikipedia).

    Minor

    • Introduces new features that extend existing functionality
    • May include bug fixes
    • May cause minor breaking changes
    • May introduce obsolete members that cause compile errors
    • Workarounds must be documented in release notes or obsolete messages

    Major

    • Introduces major new features
    • Introduces breaking changes that require considerable effort to integrate
    • Introduces a new data or protocol format that requires migration

    Conventions

    Uniqueness for official releases

    There will only ever be one artifact of an official release corresponding to a given "main" version number.

    That is, if 1.0.0.523 exists, then there will never be a 1.0.0.524. This is due the fact that the build number (e.g. 524) is purely for auditing.

    For example, suppose your software uses a NuGet package with version 1.0.0.523. NuGet will not offer to upgrade to 1.0.0.524.

    Pre-release Labels

    There are no restrictions on the labels for pre-releases. However, it's recommended to use one of the following:

    • alpha
    • beta
    • rc

    Be aware that if you choose a different label, then it is ordered alphabetically relative to the other pre-releases.

    For example, if you were to use the label pre-release to produce the version 0.9.0-prealpha21, then that version is considered to be higher than 0.0.0-alpha34. A tool like NuGet will not see the latter version as an upgrade.

    Release branches

    The name of a release branch should be the major version of that release. E.g. release/1 for version 1.x.x.x.

    Pre-release branches

    The name of a pre-release branch should be of the form feature/[label] where [label] is one of the labels recommended above. It's also OK to use a personal branch to create a pre-release build, as in mvb/[label].

    Setting the base version

    A developer uses the quino tool to set the version.

    For example, to set the version to 1.0.1, execute the following:

    quino fix -v 1.0.1.0
    

    The tool will have updated the version number in all relevant files.

    Calculating final version

    The build server calculates a release's version number as follows,

    • major: Taken from solution
    • minor: Taken from solution
    • maintenance: Read from solution
    • label: Taken from the Git branch (see below for details)
    • build: Provided by the build server

    Git Branches

    The name of the Git branch determines which kind of release to produce.

    • If the name of the branch matches the glob **/release/*, then it's an official release
    • Everything else is a pre-release

    For example,

    • origin/release/1
    • origin/production/release/new
    • origin/release/
    • release/1
    • production/release/new
    • release/

    The name of the branch doesn't influence the version number since an official release doesn't have a label.

    Pre-release labels

    The label is taken from the last part of the branch name.

    For example,

    • origin/feature/beta yields beta
    • origin/feature/rc yields rc
    • origin/mvb/rc yields rc

    The following algorithm ensures that the label can be part of a valid semantic version.

    • Remove invalid characters
    • Append an X after a trailing digit
    • Use X if the label is empty (or becomes empty after having removed invalid characters)

    For example,

    • origin/feature/rc1 yields rc1X
    • origin/feature/linux_compat yields linuxcompat
    • origin/feature/12 yields X

    Examples

    Assume that,

    • the version number in the solution is 0.9.0.0
    • the build counter on the build server is at 522

    Then,

    • Deploying from branch origin/release/1 produces artifacts with version number 0.9.0.522
    • Deploying from branch origin/feature/rc produces artifacts with version number 0.9.0-rc522

    Release Workflow

    The following are very concise guides for how to produce artifacts.

    Pre-release

    • Ensure you are on a non-release branch (e.g. feature/rc, master)
    • Verify or set the base version (e.g. quino fix -v 1.0.2.0
    • Push any changes to Git
    • Execute the "deploy" task against your branch on the build server

    Release

    • Ensure you are on a release branch (e.g. release/1)
    • Verify or set the base version (e.g. quino fix -v 1.0.2.0
    • Push any changes to Git
    • Execute the "deploy" task against your branch on the build server
    7.11.2018 - v5.2.9: Console, Services and Bug Fixes

    The summary below describes major new features, items of note and breaking changes.

    The links above require a login.

    Overview

    This is the last planned release on the 5.x branch of Quino. The future lies with Quino 6, which targets .NET Standard and .NET Core wherever possible.

    Highlights

    • Improved Console Support for Windows Services (QNO-5938)

    Breaking changes

    • Renamed AddDefaultExceptionDetailsFormatters() to UseDefaultExceptionDetailsFormatters()
    • Moved crash-reporter types to Encodo.Monitor
    • Renamed ProcessExtensions.StopChild() to StopAndClose()
    • Renamed IProcessParameters.Timeout to IProcessParameters.TimeoutInMilliseconds
    • Renamed IDataGeneratePluginInitializer to IDataGeneratorPluginInitializer
    • Plugin support has been moved from Encodo.Application.Standard to Encodo.Plugins
    • PasswordEncryptionType has been replaced with HashAlgorithm
    • GetSearchClass(IMetaClass) was moved from Quino.Meta to Quino.Builders
    • GetLayout no longer has a default value for the layoutType parameter (pass LayoutType.Detail to get the previous behavior)
    • IKeyValueNode.GetValue() has been moved to an extension method. You may need to include the namespace Encodo.Nodes.
    • Namespaces in Quino.Bookmarks have been changed from Encodo.Quino.Bookmarks.Bookmarks to Encodo.Quino.Bookmarks.
    • WPF schema-migration types have been moved from the Quino.Module.Schema.Wpfnamespace to Encodo.Quino.Module.Schema.Wpf.
    • Some testing support types have been moved from the Tests to the Testing namespace (e.g. EncodoServicesBasedTestsBase and EncodoTestsBase).
    • Introduced the IFinalizerBuilderProvider so that applications no longer need to include the MetaStandardBuilder in models.

    Finalizer Provider

    Whiile an application no longer needs to manage the insertion point of the MetaStandardBuilder and therefore no longer needs to override PostFinalize() instead of a more relevant method, this is a breaking change for certain situations. For example, if a builder overrode PostFinalize() and expected the finalizer builders included in MetaStandardBuilder to have already run previously.

    The workaround is to either:

    • Rewrite the logic to avoid depending on expressions/model added by the finalizer builders. (this is what we ended up doing in Punchclock).
    • Add the builder to the list of finalizer builders (in which case it will be executed last). You can customize the finalizer builders as with an other IProvide using something like the following in your application startup.
    application.Configure<IFinalizerBuilderProvider>(
      p =>
      {
        p.Register<MyOwnFinalizerBuilder>();
        p.Remove<FallbackLayoutBuilder>();
      }
    );
    

    Relation Captions

    Automatic generation of relation captions has changed slightly.

    Whereas previously, the captions of the target class were always used, the FallbackCaptionBuilder now only does this if the name of the relation has not been changed from the default.

    If the name was changed to something else, then that name is used for relation captions. For example, if you make a relation from a Company to a Person called People, then Quino will still use the captions from the class. This allows your application to set the caption on the class and it will be used for many relations.

    However, if you create a similar relation, but rename it to CEO, Quino will no longer use the class captions, since in this case Person and People (and translations) are no longer appropriate. In this case, CEO and CEOs is more appropriate.

    In this case, the captions in the default language will be more appropriate but the captions for other languages previously taken from the class will no longer be used on the relation.

    31.10.2018 - v6.0: .NET Standard & Authentication

    The summary below describes major new features, items of note and breaking changes.

    The links above require a login.

    Overview

    At long last, Quino enters the world of .NET Standard and .NET Core. Libraries target .NET Standard 2.0, which means they can all be used with any .NET runtime on any .NET platform (e.g. Mac and Linux). Sample applications and testing assemblies target .NET Core 2.0. Tools like quinogenerate and quinofix target .NET Core 2.1 to take advantage of the standardized external tool-support there.

    Furthermore, the Windows, Winform and WPF projects have moved to a separate solution/repository called Quino-Windows.

    Quino-Standard is the core on which both Quino-Windows and Quino-WebAPI build.

    • All core assemblies target .NET Standard 2.0.
    • All assemblies in Quino-Windows target .NET Framework 4.6.2 because that's the first framework that can interact with .NET Standard (and under which Windows-specific code runs).
    • All assemblies in Quino-WebAPI currently target .NET Framework 4.6.2. We plan on targeting .NET Core in an upcoming version (tentatively planned for v7).

    Highlights

    • Target .NET Standard and .NET Core from Quino-Standard
    • Split Windows-specific code to Quino-Windows
    • Improve authentication API to use IIdentity everywhere (deprecating ICredentials and IUserCredentials).

    Breaking Changes

    6.0 is a pretty major break from the 5.x release. Although almost all assembly names have stayed the same, we had to move some types around to accommodate targeting .NET Standard with 85% of Quino's code.

    APIs

    We've tried to support existing code wherever possible, but some compile errors will be unavoidable (e.g. from namespace changes or missing references). In many cases, R#/VS should be able to help repair these errors.

    These are the breaking changes that are currently known.

    • Moved IRunSettings and RunMode from Encodo.Application to Encodo.Core.

    References

    Any .NET Framework executable that uses assemblies targeting .NET Standard must reference .NET Standard itself. The compiler (MSBuild) in Visual Studio will alert you to add a reference to .NET Standard using NuGet. This applies not just to Winform executables, but also to any unit-test assemblies.

    Tools

    One piece that has changed significantly is the tool support formerly provided with Quino.Utils. As of version 6, Quino no longer uses NAnt, instead providing dotnet-compatible tools that you can install using common .NET commands. Currently, Quino supports:

    • dotnet quinofix
    • dotnet quinogenerate
    • dotnet quinopack

    Please see the tools documentation for more information on how to install and use the new tools.

    The standalone Winforms-based tools are in the Quino-Windows download, in the Tools.zip archive.

    • Quino.Migrator
    • Quino.PasswordEncryptor

    Quino.Utils is no longer supported as a NuGet package.

    20.8.2018 - Seilpark Rheinfall 2018

    Encodo took a trip to the north to the beautiful Rhine Falls (Rheinfall), which served as a backdrop for a team event at a rope/adventure park. There was something for everyone and many of us were surprised at how much we were willing to take on as we swung around in the trees.

    We started off with breakfast, then played Tarzan for a few hours and finished up with a long lunch in the afternoon. A few went to the river to go swimming afterwards, while a couple of others (Marco/Tom) rode their bikes back home.

    There are also a couple of videos:

    14.8.2018 - v5.0.15: bug fixes for Winform and Report Manager

    The summary below describes major new features, items of note and breaking changes. The full list of issues is in the release notes and is available to those with access to the Encodo issue tracker.

    Highlights

    Breaking changes

    • No known breaking changes.
    7.8.2018 - SPA state management libraries

    Abstract

    Encodo has updated its technology stack for SPAs. Current and future projects will use a combination of React Component States, React Contexts and Redux:

    • Use React Component States to manage state that is used only in a single component.
    • Use React Contexts to manage presentational state for component hierarchies.
    • Use Redux to manage global or persistent state.

    The following article provides justification and reasoning for the conclusions listed above.

    Overview

    Encodo have undertaken a number of Single Page Application (SPA) projects over the last several years. During this time, web technologies, common standards and best practices have changed significantly. As such, these projects each had different configurations and used different sets of web technologies.

    The last two years have brought a reduction in churn in web technologies. Encodo have therefore decided to evaluate SPA libraries with the goal of defining a stack that will be stable for the next few years. The outcome of this evaluation proposes a set of best practices in architecting an SPA, and most importantly, architecting an SPA’s state.

    Participants

    • Marc Duerst
    • Marco von Ballmoos
    • Remo von Ballmoos
    • Richi Buetzer
    • Tom Szpytman

    Introduction

    Having undertaken an earlier evaluation of SPA rendering libraries, Encodo’s SPA projects have all relied upon the Javascript library React. To date, the company still feels that React provides an adequate and stable platform upon which to build SPAs.

    Where the company feels its knowledge can be improved upon, is how state should be structured in an SPA, and which SPA state libraries, or combination of libraries, provide the most maintainable, stable and readable architectures. As such, this evaluation will only focus on discussing SPA-state libraries and not SPA-rendering libraries.

    Requirements

    Encodo focusses on both the building and maintenance of elegant solutions. It is therefore paramount that these software solutions are stable, yet future-proof in an ever-changing world. Many of Encodo’s clients request that solutions be backward-compatible with older browsers. An SPA state library must therefore adhere to the following criteria:

    • The library must have a moderately-sized community
    • The library must have a solid group of maintainers and contributors
    • Typescript typings must be available (and maintained)
    • The library must be open-source
    • The library must support all common browsers, as far back as IE11
    • The library must have a roadmap / future
    • Code using the library must be maintainable and readable (and support refactoring in a useful manner)

    Candidates

    Redux

    Redux was released over three years ago and has amassed over 40,000 stars on Github. The project team provides a thorough set of tutorials, and software developers are additionally able to find a plethora of other resources online. Furthermore, with almost 15,000 related questions on StackOverflow, the chances of finding unique problems that other developers haven’t previously encountered are slim. Redux has over 600 contributors, and although its main contributors currently work for Facebook, the library is open source in its own right and not owned by Facebook.

    Redux is an implementation of the Flux pattern; that is, you have a set of stores that each hold and maintain part of an application state. Stores register with a dispatcher, and by connecting to the dispatcher, receive notifications of events (usually as a result of a user input, but often also as a result of an automated process, e.g. a timer which emits an event each second). In the Redux world, these events are called actions. An action is no more than a Javascript object containing a type (a descriptive unique id) and optional additional information associated with that event.

    Example 1 – A basic Redux action

    Imagine a scenario where a user clicks on a button. Clicking the button toggles the application’s background colour. If the button were connected to Redux, it would then call the dispatcher and pass it an action:

    {
      type: ‘TOGGLE_BACKGROUND_COLOUR’
    }
    

    Example 2 – A Redux action with a payload

    Suppose now the application displayed an input field which allowed the user to specify a background colour. The value of the text field could be extracted and added as data to the action:

    {
      type: ‘TOGGLE_BACKGROUND_COLOUR’,
      payload: {
        colour: ‘red’ // Taken from the value of the text field, for example
      }
    }
    

    When the dispatcher receives an action, it passes the action down to its registered stores. If the store is configured to process an action of that type, it runs the action through its configuration and emits a modified state. If not, it simply ignores the action.

    Example 3 – Processing an action

    Suppose an application had two stores:

    • Store X has an initial state { colour: ‘red’ } and is configured to process TOGGLE_BACKGROUND_COLOUR actions. If it encounters an action of this type, it is configured to set its state to the colour in the action’s payload.

    • Store Y has an initial state { users: [] } and is configured to process USER_LOAD actions. If it encounters an action of this type, it is configured to set its state to the users in the action’s payload.

    Suppose the following occurs:

    • A TOGGLE_BACKGROUND_COLOUR action is sent to the dispatcher with payload { colour: ‘green’ }.

    The result would be:

    • Store Y ignores this action as it is not configured to process actions of the TOGGLE_BACKGROUND_COLOUR type. It therefore maintains its state as { users: [] }.

    • Store X on the other hand, is configured to process TOGGLE_BACKGROUND_COLOUR actions and emits the modified state { colour: ‘green’ }.

    Views bind the stores and dispatcher together. Views are as their name suggests; the application’s visual components.

    When using Redux in combination with React, Views, in the Redux sense, are React components that render parts of the state (e.g. the application’s background colour) and re-render when those parts of the state change.

    Redux doesn’t have to be used in conjunction with React, so the general definition of a view is a construct that re-renders every time the part of the state it watches changes. Views are additionally responsible for creating and passing actions to the dispatcher. As an example, a view might render two elements; a div displaying the current colour and a toggle button which, when clicked, sends a TOGGLE_BACKGROUND_COLOUR action to the dispatcher.

    Figure 1: The flow of a Redux application

    Pros

    Software written following Redux’s guidelines is readable, quick to learn and easy to work with. Whilst Redux’s verbosity is often cited as a pitfall, the level of detail its verbosity provides helps debugging. Debugging is also aided by a highly detailed, well-constructed, browser extension; Redux DevTools. At any given point in time, a developer can open up Redux DevTools and not only be presented with an overview of an application’s state, but the effect of each action on the state. That’s certainly a tick in the box for Redux when it comes to ease of debugging.

    Pairing Redux with React is as simple as installing and configuring the react-redux library. The library enforces a certain pattern of integrating the two, and as such, React-Redux projects are generally structured in similar ways. This is incredibly beneficial for developers, as the learning curve when jumping into new Redux-based projects is significantly reduced.

    Redux also allows applications to rehydrate their state. In non-Redux terms, this means that when a Redux application starts, a developer can provide the application with a previously saved state. This is incredibly useful in instances where an application’s state needs to be persisted between sessions, or when data from the server needs to be cached. As an example, suppose our application sends data to and from an authenticated API and needs to send an authentication token on each request. It’d be impractical if this token were to be lost every time the page was refreshed or the browser closed. Redux could instead be configured so that the authentication token always be persisted and then re-retrieved from the browser’s Local Storage when the application started. The ability to re-hydrate a state can also lead to significantly faster application start-up times. In an application which displays a list of users, Redux could be configured to cache/persist the list of users, and on startup, display the cached version of that list until the application has time to make an API call to fetch the latest, updated list of users.

    All in all, Redux proves itself to be a library which is easy to learn, use and maintain. It provides excellent React integration and the community around it offer a plethora of tools that help optimise and simplify complicated application scenarios.

    Cons

    As previously mentioned, Redux is considered verbose; that is, a software developer has to write a lot of code in order to connect a View to a Dispatcher. Many regard this as ‘boilerplate’ code, however, the author considers this a misuse of the word ‘boilerplate’, as code is not repeated, but rather, a developer has to write a lot of it.

    Additionally, while Redux describes the flow and states very well, its precision negatively impacts on refactoring and maintainability. If there is significant change to the structure of the components, it's very difficult to modify the existing actions and reducers. It's not hard to lose time trying to find the balance between refactoring what you had and just starting from scratch.

    Example 4 – The disadvantages of Redux

    class Foo Extends React.Component {
      render() {
        return (
          <div onClick={this.props.click}>
            {this.props.hasBeenClicked
              ? “I’ve been clicked”
              : “I haven’t been clicked yet”
            }
          </div>
        );
      }
    }
    

    Consider the bare-bones example above that illustrates:

    • A component which starts by displaying the string “I haven’t been clicked yet” and then changes to display the string “I’ve been clicked” when the initial string is clicked.

    If we were to use Redux as the state store for this scenario, we’d have to:

    • Create and define a reducer (Redux’s term for a store’s configuration function) and a corresponding action
    • Configure this component to use Redux. This would involve wiring up the various prop types (those passed down from the parent component, a click action to send to the dispatcher and a hasBeenClicked prop that needs to be read out from the Redux state)

    What could remain a fairly small file if we were to use, say, class Foo’s component state (see the React Component State chapter for details), would end up as a series of long files if we were to use Redux. Clearly Redux’s forte doesn’t lie in managing a purely presentational component’s state.

    Furthermore, suppose we had fifty presentational components like Foo, whose states were only used by the components themselves. Storing each component’s UI state in the global application state would not only pollute the Redux state tree (imagine having fifty different reducers/actions just to track tiny UI changes), but would actually slow down Redux’s performance. There’d be a lot of state changes, and each time the state changed, Redux would have to calculate which views were listening on that changed state and notify them of the changes.

    Managing the state of simple UI/presentational components is therefore not a good fit for Redux.

    Summary

    Redux’s strengths lie in acting as an application’s global state manager. That is, Redux works extremely well for state which needs to be accessed from across an application at various depths. Its enforcement of common patterns and its well-constructed developer tools means that developers can reasonably quickly open up unfamiliar Redux-based projects and understand the code. Finally, the out of the box ability to save/restore parts of the state means that Redux outweighs most other contenders as a global state manager.

    Mobx

    At the time of writing, as with Redux, Mobx was first released over three years ago. Although still sizeable, its community is much smaller than Redux’s; it has over 16,000 stars on Github and almost 700 related questions on StackOverflow. The library is maintained by one main contributor, and although other contributors do exist, the combined number of their commits is dwarfed by those from the main contributor.

    In its most basic form, Mobx implements the observer pattern. In practice, this means that Mobx allows an object to be declared as an ‘observable’ which ‘observers’ can then subscribe to and receive notifications of the observable object’s changes. When combining Mobx with React, observers can take the form of React components that re-render each time the observables they’re subscribed to change, or basic functions which re-run when the observables they reference change.

    Pros

    What Mobx lacks in community support, it makes up for in its ease of setup. Re-implementing Example 4 above using Mobx, a developer would simply:

    • Declare the component an observer
    • Give the class a boolean field property and register it as an observable

    Example 5 – A simple Mobx setup

    @observer
    class Foo Extends React.Component {
    
      hasBeenClicked = observable(false);
    
      render() {
        return (
          <div onClick={() => this.hasBeenClicked.set(true)}>
            {this.hasBeenClicked.get()
              ? “I’ve been clicked”
              : “I haven’t been clicked yet”
            }
          </div>
        );
      }
    }
    

    Short and sweet. Mobx at its finest.

    The tree-like state structures required by Redux can feel rather limiting. In contrast, a developer using Mobx as a global state manager could encapsulate the global state in several singleton objects, each making up part of the state. Although there are recommended guidelines for using this approach (Mobx StoreMobx project structure), these aren’t as readily enforced by Mobx as Redux does its recommended ways of structuring code.

    Mobx proves itself as a worthy candidate for managing the state of UI/presentational components. Furthermore, it offers the flexibility of being able to declare observables/observers anywhere in the application, thus preventing pollution of the global application state and allowing some states to be encapsulated locally within React components. Finally, when used as a global application state manager, the ability to model the global state in an object-orientated manner can also seem more logical than the tree structure enforced by Redux.

    Cons

    Mobx seems great so far; it’s a small, niche library which does exactly what it says on the tin. Where could it possibly go wrong? Lots of places…

    For starters, Mobx’s debugging tool is far inferior to the host of tools offered by the Redux community. Mobx-trace work perfectly well when trying to ascertain who/what triggered an update to an observable, or why an observer re-rendered/re-executed, but in contrast to Redux DevTools, it lacks the ability to gain an overview of the entire application state at any given point in time.

    Moreover, Mobx doesn’t come with any out of the box persist/restore functionality, and although there are libraries out there to help, these libraries have such small user bases that they don’t provide Typescript support. The Mobx creator has, in the past, claimed that it wouldn’t be too hard for a developer to write a custom persistence library, but having simple, out of the box persist/restore functionality as Redux does is still favourable.

    Beyond the simplicity presented in Example 5, Mobx is a library that provides an overwhelming number of low-level functions. In doing so, and in not always providing clear guidelines describing the use-cases of each function, the library allows developers to trip up over themselves. As examples, developers could read the Mobx documentation and still be left with the questions:

    • When is it best to use autorun vs reaction vs a simple observer?
    • When should I “dispose” of observable functions?

    In summary, the relatively small community surrounding Mobx has led to the library lacking in a solid set of developer tools, add-on libraries and resources to learn about its intricacies. Ultimately this is a huge negative aspect and should be heavily considered when opting to use Mobx in an SPA.

    Summary

    As a library, Mobx has huge potential; its core concepts are simple and the places in which it lacks could easily be improved upon. Its downfall, however, is the fact that it only has one main contributor and a small community surrounding it. This means that the library lacks, and will lack, essentials such as in-depth tutorials and development tools.

    Added to this, as of Mobx v5, the library dropped support for IE11. In doing so, the library now fails to meet Encodo’s cross-compatibility requirements. The current claim is that Mobx v4 will remain actively supported, but with a limited number of contributors, it is debatable whether or not support for v4 will remain a priority.

    Beyond the lack of IE11 support, Mobx's lack of coherent guidelines, sub-par debugging tools and free reign given to developers to architect projects as they please makes for problematic code maintenance.

    React Component State

    React was initially released over five years ago and from its inception, has always offered a way of managing and maintaining state. Here we must note, that whilst a state management system exists, it is not intended to be used as a global state management system. Instead, it is designed to function as a local state system for UI/presentational components. As such, the evaluation of React Component states will only focus on the benefits and drawbacks of using it as a local state manager.

    Pros

    React component state is an easy to learn, easy to use framework for managing a small UI state.

    Example 6 – Component state

    class Foo Extends React.Component {
      state = {
        hasBeenClicked = false
      };
    
      render () {
        return (
          <div
            onClick={() => this.setState({ hasBeenClicked: true })}
          >
            {this.state.hasBeenClicked
              ? “I’ve been clicked”
              : “I haven’t been clicked yet”
            }
          </div>
        );
      }
    }
    

    Refreshingly simple.

    Configuring a Component state can be as simple as:

    • Defining a component’s initial state
    • Configuring the component’s render function to display that state
    • Binding to UI triggers (e.g. onClick methods) which update the component’s state, thus forcing a re-render of the component

    React Component State is just as concise as the similar MobX example above, without introducing a separate library.

    Cons

    React component states aren’t well architected to managing the states of hierarchies of UI components.

    Example 7 – The drawbacks of using Component state

    class Foo Extends React.Component {
      state = {
         hasBeenClicked: false,
         numberOfClicks: 0
      };
    
      onClick = () => {
        return this.setState(
          (previousState) =>
            ({
              hasBeenClicked: true,
              numberOfClicks: previousState.numberOfClicks + 1
            })
        );
      }
    
      render() {
        return (
          <div>
            <FooDisplay
              hasBeenClicked={this.state.hasBeenClicked}
              numberOfClicks={this.state.numberOfClicks}
            />
            <Button onClick={this.onClick} />
          </div>
        );
      }
    }
    
    
    class FooDisplay extends React.Component {
      render() {
        return (
          <div>
            {this.props.hasBeenClicked
              ? “I’ve been clicked”
              : <CountDisplay
                  numberOfClicks={this.props.numberOfClicks}
                />
            }
          </div>
        );
      }
    }
    
    
    class CountDisplay extends React.Component {
      render() {
        return (
          <div>
            I’ve been clicked {this.props.numberOfClicks} times
          </div>
        );
      }
    }
    
    
    class Button Extends React.Component {
      render () {
        return (
          <button onClick={this.props.onClick}>
            Click me
          </button>
        );
      }
    }
    

    Although basic, the example above attempts to illustrate the following:

    • State/state modifying functions have to be passed down through the hierarchy of components as props. If the components were split into multiple files (as is common to do in a React project), it’d become cumbersome to trace the source of CountDisplay’s props
    • FooDisplay’s only use for its numberOfClicks prop is to pass it down further. This feels a bit sloppy, but is the only way of getting numberOfClicks down to CountDisplay when using Component State.

    Summary

    React Component States are often overlooked. Yes, they are limited and only work well for a single specific use case (managing the UI state of a single component), but component states do this extremely well. Software developers often claim that they need more fully-fledged state management libraries such as Redux or Mobx, but if just used to manage UI states, they’d probably be mis-using these libraries.

    React component state is as its name suggests; a way of managing state for a single component. React has this functionality built-in, begging the question; is there ever really a use-case for using an alternative library to manage a single component’s state?

    React Contexts

    React 16.3 introduced a public-facing ‘Context’ API. Contexts were part of the library prior to the public API, and other libraries such as Redux were already making use of it as early as 2 years ago.

    React Contexts excel where the Component State architecture begins to crumble; with Contexts, applications no longer have to pass state data down through the component tree to the consumer of the data. Like Redux, React Contexts aren’t well suited to tracking the state of single presentational components; an application tracking single component states with Contexts would end up being far too complicated. Rather, React Contexts are useful for managing the state of hierarchies of presentational components.

    Pros

    React Contexts allow developers to encapsulate a set of UI components without affecting the rest of the application. By encapsulating the state of a hierarchy of UI components, the hierarchy can be used within any application, at any depth of a component tree. Contexts furthermore allow developers to model UI state in an OO structure. In this sense, React Contexts (in addition to React Component State) provide many of the advantages of Mobx (again, without pulling in a separate library).

    UI states are quite often a set of miscellaneous booleans and other variables which don’t necessarily fit into hierarchical tree structures. The ability to encapsulate these variables into one, or several objects is much more fitting. The last benefit of using Contexts is that they allow all components below the hierarchy’s root component to retrieve the state without interfering with intermediary components in the process.

    Example 8 – React Contexts

    class VisibilityStore = {
      isVisible = true;
      toggle = () => this.isVisible = !this.isVisible;
    }
    
    const VisibilityContext = React.createContext(VisibilityStore);
    
    class Visibility extends React.Component {
      store = new VisibilityStore();
      render() {
        return (
           <VisibilityContext.Provider value={store}>
             <VisibilityButton />
             <VisibilityDisplay />
           </VisibilityContext.Provider>
        );
      }
    }
    
    class VisibilityButton extends React.Component {
      render() {
        return (
          <VisibilityContext.Consumer>
            {(context) => <button onClick={context.toggle} />}
          </VisibilityContext.Consumer>
        );
      }
    }
    
    class VisibilityDisplay extends React.Component {]
      render() {
        return (
          <VisibilityContext.Consumer>
            {
              (context) =>
                <div>
                  {context.isVisible
                    ? ‘Visible’
                    : ‘Invisible’
                  }
                </div>
            }
          </VisibilityContext.Consumer>
        );
      }
    }
    

    The example above exemplifies modelling the UI state as an object (VisibilityStore), retrieving the UI state (VisibilityDisplay) and finally updating the state (VisibilityButton). Although a simple example, it depicts how state can be accessed at various depths of the component tree without affecting intermediary nodes.

    Cons

    Using Contexts to manage the state of single components would be overkill. Contexts are also ill-equipped to be used as global state managers; they lack a persist/re-load mechanism, and additionally, lack debugging tools which would help provide an overview of the application’s state at any given point in time.

    Summary

    React Contexts are well suited to a single use-case; managing the state of a group of UI components. Contexts, on their own, aren’t the solution to managing the state of an entire SPA, but the React team’s public release of the Context API comes at a time where it is common to see SPA states bloated full of UI-related state. Developers should therefore seriously consider trimming down their global application states by making use of Contexts.

    Alternatives

    Although the main React-compatible state management libraries have already been evaluated in this document, it is important to evaluate alternative libraries that are growing in popularity.

    Undux

    Undux was first released a year ago and sells itself as a lightweight Redux alternative. In just under a year it has amassed nearly 1000 Github stars. That being said, the library still lacks a community around it; there’s still only one main contributor and resources on the library are scarce. Having a single contributor means that the library suffers from under-delivering on essential features like state selectors.

    That aside, Undux seems like a promising library; it strips out the verbosity of React, works with React’s debugging tools, supports Typescript and is highly cross-browser compatible. If the size of Undux’s community and number of contributors were to increase, it could be a real contender to Redux.

    React Easy State

    Like Undux, React Easy State was released over a year ago and has amassed just over 1000 Github stars. It sells itself as an alternative to Mobx and has gained a strong community around it. Both official and non-official resources are plentiful, Typescript support comes out of the box and the library’s API looks extremely promising. React Easy State, however, cannot be considered an SPA management library for Encodo’s purposes as it doesn’t support (and states it will never support) Internet Explorer.

    Conclusion

    Software libraries are built out of a need to solve a specific problem, or a set of specific problems. Software developers should be mindful of using libraries to solve these sets of problems, and not overstretch libraries to solve problems they weren’t ever designed to solve. Dan Abramov’s blogpost on why Redux shouldn’t be used as the go-to library for all SPA state management problems highlights this argument perfectly.

    In light of this, Encodo propose that the use of multiple libraries to solve different problems is beneficial, so long as there are clear rules detailing when one library should be used over another. Having evaluated several different SPA state management libraries, Encodo conclude by suggesting that SPAs should use a combination of Redux, React Contexts and React Component states:

    • React Component states should be used to manage the state of individual presentational components whose states aren't required by the rest of the application.
    • React Contexts should be used to manage the state of hierarchies of presentational components. Again, beyond the hierarchies, the states encapsulated by Contexts shouldn’t be required by the rest of the application.
    • Redux should be used to store any state that needs to be used across the application, or needs to be persisted and then re-initialised.

    Mobx has been omitted from the list of recommendations, as upon evaluation, Encodo conclude that it does not meet their requirements. Mobx is a library which exposes a large surface area, thereby offering solutions to a wide range of problems, but not providing a small set of optimised solutions. Many of the advantages of Mobx – mapping state in an OO manner and concise, simple bindings – are provided by React Component State and React Context.

    The contender to Mobx, React Easy State, has also been omitted from Encodo’s recommendations, as although it is certainly a promising library with a growing community surrounding it, the library doesn’t support Internet Explorer and therefore does not fulfil Encodo’s requirements.

    Finally, although Undux could be a strong contender in replacing Redux, at the time of writing, Encodo feel that the library is not mature enough to be a production-ready, future proof choice and therefore also exclude it from their list of recommendations.

    19.7.2018 - Training #1: Programming with .NET, C# & Quino

    This is the first in a series of three 4-hour trainings designed to introduce a team of software developers with little to no .NET experience to the concepts, tools and world of .NET and Quino

    19.6.2018 - WintiWebDev Meetup June 2018

    Encodo was pleased to be able to host and participate in the June 2018 meetup yesterday evening.

    We heard about usability and user experience from Luca Honegger of Kleinfach GmbH. He emphasized that projects would be well-served by getting users involved in the process early on. He cautioned that user feedback must be taken with a grain of salt, but that it's always essential—if the target users can't use your application, then it doesn't matter how much you can "prove" that it's good design. Early feedback sessions can also be a great way of refining requirements that users can't formulate without "seeing" something.

    Next, we learned about optimizing web-page loading speed from David Gunziger of smoca. He discussed the advantages of HTTP2 as well as aggressive caching, inlining of resources, pipelining requests and tweaking the content to let the browser display content as quickly as possible. He managed to reduce the initial-loading time of his company's web page by over 50%.

    Finally, our own Richard Bützer (just started last month!) presented a fun-but-somewhat-sobering quiz about JavaScript conversions. Is an array equal to an array? Is it equal to true? What about 1? It was a wild ride through some very non-intuitive type conversions that led to some rousing discussions about how to prevent these JavaScript weaknesses from getting in the way of producing quality software. Everybody was able to try their hand at answering questions with Kahoot.

    Afterwards, there were drinks and snacks and lively conversation. All in all, 25 people attended. Thanks to everybody for coming!

    15.3.2018 - Quino Roadmap

    Quino Roadmap

    This document is about the future of Quino. See the release notes for the past.

    The following releases reflect current planning. Changing needs and requirements may affect the order and scheduling of various components. We will update the schedule here if it changes.

    6.0.1 — December 2018

    • Improve documentation
    • Finalize authentication changes/API

    6.1 — January 2019

    • Finalize Authorization/Security

    6.2 — February 2019

    • Remoting driver update - adapt security

    7.0 — Spring 2019

    • Move extension methods to components
    • Standardize namespaces, projects and dependencies
    26.2.2018 - The Road to React

    This talk discusses the motive behind our move to React, including requirements, candidates and a high-level description of React with learning resources

    19.2.2018 - How do I DI?

    This talk discusses the terms and concepts of DI, IOC and containers. It includes code smells, recommended patterns and tips for refactoring.

    6.2.2018 - Cookies 2017

    Every year, Encodo gets together and puts something together for our customers. Several years ago, we baked cookies ... and those were really, really popular.

    For 2017, we bowed to customer pressure and baked cookies again, digging up our hand-made Encodo-logo cookie forms and baking traditional Swiss Christmas cookies.

    6.2.2018 - Saturn 5 Adventskalendar 2017

    Every year, Encodo hangs an advent calendar in the office, usually filled with chocolate and trinkets. A few of the years, we've had puzzles and larger toys that were split into several pieces.

    This year, we split up the Legos Saturn 5 rocket over the workdays leading up to Christmas. Beforehand, though, Karin, Kath, Remo and Marco put the rocket together—just to see what it looks like.

    26.1.2018 - Encodo's new web site

    As you can see, Encodo finally has a new web site!

    Motive

    We'd had the same design for many years and it was time for a refresh..

    What did we want to change?

    • Improve the design and navigation
    • Make it mobile-friendly
    • Make it easier for Encodo employees to add/update content
    • Improved integration of comments
    • Move to a platform more familiar for more developers at Encodo
    • Make our site representative of our work

    Design

    We didn't do the design ourselves (because we're not really designers). Instead, we contracted our partners at Ergosign to come up with a design for us and we think they did a great job (as usual).

    Requirements

    The previous web site[^1] had the following features:

    • A full-featured album and picture manager
    • A full-featured blog with comments/email-publication/RSS
    • A full-featured text-formatting language for all text
    • Attachments for blogs/external content
    • Security features to restrict access
    • Integration with a separate ASP.NET site for collecting job applications.

    On top of that, we wanted:

    • LDAP/AD integration
    • All content editable/managed by the same back-end
    • Improved search

    Candidates

    On the server side, we evaluated a bunch of approaches:

    • Stick with the existing PHP web site but move static content into the back-end
    • Build the entire site from scratch with Quino
    • Use another blogging framework. Candidates:
      • Umbraco
      • WordPress
      • MovableType, Nucleus, GreyMatter, etc.
      • Static Site Generators (e.g. Jekyll)

    Our Approach

    After much deliberation and some POCs, we went with Umbraco, a framework written in and for .NET C#.

    This approach entailed:

    • Customizing the Umbraco look-and-feel to use the new design
    • Integrating a job-application web API server (written with Quino)
    • Writing an exporter in PHP that exposes a JSON API to return blogs, articles, journals, pictures and albums as Markdown content with Base64-encoded attachments and pictures.
    • Writing an importer in C# that marshals the data returned by the PHP JSON API to Umbraco objects and data

    What's Next?

    We've come a long way toward our goal, but a web site is an ongoing project.

    We've incurred a bit of technical debt on our way to release, so a first step will be to convert some inline JavaScript and CSS to shared TypeScript and LESS. We're also improving our support for mobile devices as we test more.


    [^1] We were using the earthli WebCore, a PHP CMS written by Marco.

    13.11.2017 - Team Event: Summer's End in Ticino!

    imageIn late September, Encodo closed out the summer with a four-day weekend at a rented house in Tenero-Contra. We were 300 meters above the valley floor, clinging to the slopes of the Verzasca Valley just under Mergoscia. We had a commanding view of Lago Maggiore, Monte Ceneri and Monte Tamaro.

    In addition to all of the pictures and the calendar, there are four short journal entries that describe how we passed the time:

    Click here to see the pictures!

    13.11.2017 - Encodo Networking Event 2017.2

    Encodo held its second (and final) networking event of 2017 on November 2nd with Marco presenting Cross-Platform Development for Mobile Apps (slides in English/presentation in Swiss-German).

    Thanks to everyone who attended!

    The abstract is included below.

    imageThis talk starts off discussing a laundry list of requirements and project details that impact on mobile development and can affect which tools, frameworks and libraries you choose to support your work. The second part covers the available frameworks with extra detail where Encodo has experience (many of them). They include: Cordova, PhoneGap, Ionic, Xamarin, Native Development and Flutter.


    > Spoiler Alert: Encodo's most recent experience with Xamarin has been extremely positive - it's our framework of choice now.
    8.11.2017 - Contra-Tenero 2017

    Encodo had a 4-day team weekend in Tenero-Contra, Ticino in the south of Switzerland. The pictures document the journey to Contra (by car, bike and train), the long weekend and the journey back north.

    2.11.2017 - Cross-platform Mobile Development

    This talk discusses tools, techniques and experiences in mobile development.

    14.6.2017 - Networking Event 2017.1 and upcoming WWDT Talk

    Encodo held its first networking event of 2017 on June 1st with Marco presenting A Checklist for new Projects (slides in English/presentation in Swiss-German).

    Thanks to everyone who attended!

    If you missed it and would like to see the talk, Marco will be presenting again at winti web dev/talks on June 19th, 2017. The talk will be in English this time.

    The abstract is included below.

    imageThis talk discusses a checklist of concepts for writing software. Which ones apply? If so, how will you address them? A must for new projects, but also very useful for ongoing, legacy or inherited projects. We'll quickly skim several groups of concepts, and then focus mainly on "core software components".

    If you can't make it, the updated slides are available online.

    1.6.2017 - A Checklist for new Projects

    This talk discusses a checklist of concepts for writing software. Which ones apply? If so, how will you address them? A must for new projects, but also very useful for ongoing, legacy or inherited projects. We'll quickly skim several groups of concepts, and then focus mainly on "core software components".

    20.4.2017 - Segway Tour 2017

    On a warm spring day, we took an afternoon off for lunch and a Segway Tour of Winterthur with Segway City Tours. After an introduction on a flat plaza by the Zeughaus, we cruised all over the city for hours, stopping on the Goldenberg and at the Oskar Reinhart Museum.