Many projects I’ve undertaken have required programming in languages or with frameworks with which I had no previous experience. This is not uncommon in software engineering, as most aspects of programming are transferable between different languages and frameworks. But there are often fundamental differences in how you must think and implement solutions. A mentor once told me that you need a good "forgettery." What this means is when programming in a different language or framework, you have to remember what you have to forget. When using an unfamiliar language or framework, you don't yet know what will be transferable and what you have to forget.
The forgettery is the place in which you keep all the things you must forget in order to program in a different language or to use a different framework. Alongside what one must forget is what one must remember to fill in those gaps. These can be specific differences such as not using the Python enumerate function in Ruby and instead using the each_with_index method. Or more complex differences such as remembering how to solve a diamond inheritance conflict. The large differences are often less likely to cause mistakes, as those take more thought to implement the small differences can slip through while programming, left to be caught later by compile errors or a linter program. The details kept in a forgettery do not need to be complete, especially for the more subtle differences. Sometimes it is enough to remember a difference exists, and what keywords can be used to find details about it in the documentation.
Programming languages are very diverse; not only do they differ in syntax, but also in paradigms. Sometimes a single language can have many different versions and implementations, each with significant differences. Languages that are most different in syntax and design from one another tend to be easier to transition between since the forgettery between them would be large with little overlap. On the other hand, languages with large differences from familiar ones will be the most difficult to learn.
When approaching a new language it is a good strategy to first find where the language overlaps with your current knowledge. Look at where the syntax is similar for common logical operations, such as branching and looping. If the languages have or support the same paradigms, look to how common design patterns and concepts are implemented. Paradigm similarity can be tricky, as many aspects are language- or implementation-specific, such as if an object system supports multiple inheritance and how the diamond problem is mitigated. A language may support a paradigm design pattern natively, such as C# support for the Observer pattern. Other times a design pattern doesn't work in a language; in those cases, there are likely idiomatic ways that the language community has devised to address them.
This research should not be done all at once. It is best to begin programming based on what you know, then once an unknown is uncovered it can be researched and added to the forgettery. This strategy will lead to some technical debt and eventual refactoring or rewrite, but this should not be a deterrent to starting the project at hand. You can't finish a project you haven't started. This research can be complicated for languages that have tighter integration with a framework, such as C# and .Net, or Swift and Cocoa, as code examples and idioms may be implemented with a specific framework version.
Frameworks are important in programming as they provide a foundational toolkit to implement an application based on common programming concepts. Frameworks tend to be the most difficult to research because common concepts are implemented in different ways and are more idiosyncratic. The best approach when learning a new framework is to work with the framework. Do not try to implement something clever, or make up a different solution that some aspect of the framework already solves. While it may end up being beneficial, now is not the time to experiment; now is the time to become accustomed to working with the new framework as its authors intended. The adage of "Learn the rules. Then break some" applies well here.
Most of the overlap in knowledge between different frameworks will be in concepts. The way to implement those concepts will be very different, often depending on features of the language and framework specific idioms. The best use of a forgettery when it comes to frameworks is in remembering what concepts have a deficient implementation. An object-relational mapping (ORM), for example, must provide a way to query the database by providing a language specific API which is then converted into database specific commands, most often using SQL. While you may want to solve a specific problem with a certain feature of SQL or the database in mind, finding out how to implement that in a framework's ORM can be difficult, and can end up being impossible to do without falling back to raw SQL. Being able to avoid a solution that can't be implemented well will save valuable time.
Recently I have taken on projects that have to lead me through this process of building a new forgettery.
The University of Rochester - The Hive project was the first project in which I utilized Angular.js and C# with .NET. Having to learn a new language and two new frameworks at the same time was challenging. Compounding the difficulty was the need to match the technical environment, tools and processes of UR. Using the strategies outlined and the best practices I could discern from industry blogs and documentation, I was able to start developing quickly based on my current knowledge. I prioritized tasks that took advantage of my current knowledge and left more complex tasks to learn later when I was sure I would need to learn them. Learning .NET was a good example of learning the rules first. The common approach to solving some problems in that framework seemed strange at first and the urge to find a different solution outside of the framework's implementation was strong. But frameworks are popular because they solve problems for very many people and if the solutions work for many, they should be good enough for me. Even though there was much learning involved in this project, we delivered a high-quality application on schedule. If you want to learn more about this project, read the case study.
The imgix - Page Weight project involved revamping an existing application. Because of this, it was important to stick to the current development process and conventions being used. This project was developed in Ruby on Rails, a framework whose philosophy is "convention over configuration." This means that the framework should have sensible defaults and behave as expected. And specifically in the case of Rails, it means that the directory structure and project files are set in the framework. I know the base concepts that web frameworks are meant to address, so it was just a task of finding and working within the pre-existing conventions. This proved to be tedious at times as the conventions are not always evident, and it requires some time to discern them through research and testing. But knowing the base concepts, and how they were solved in other frameworks, guided my research and ensured that my time was well spent. You can read the case study to learn more about this project.
It is daunting to learn a new language or framework, especially if there is a deadline involved. But it is not unlike any other challenge in software engineering. Embrace that you often will not understand the problems you will face up front. Trust that your current knowledge is enough to get started. Getting started will give you insight into what common knowledge applies, and what needs to be added to your forgettery. As your forgettery grows, your ability to transition between languages and frameworks will increase, and you will become more confident in your ability to face unknowns.