What is the difference between a software framework and a software architecture?

Software frameworks are reusable “semi-finished” software for domains (such as ERP, computing, etc.) that implement common parts of the domain and provide well-defined points of variability to ensure flexibility and extensibility. In other words, the software framework is the softwarenation of the results of domain analysis and the template for the final application in the domain.

With the expansion of software scale, wide application and the development of software reuse technology, the software reuse based on subroutine and class has a lot of shortcomings:

(1) The library of the subroutine is becoming more and more huge, which makes it difficult for its users to master

(2) Most classes are too small to do all the useful work by themselves

It is for these reasons that a set of classes (modules) are considered as a whole in reuse, resulting in a software framework. The software framework contains at least the following components:

(1) A series of modules to complete the calculation become components

(2) The relationship between components and the interaction mechanism

(3) A series of variable points (hot spots, or adjustment points)

(4) Behavior adjustment mechanism of variable point

Developers through the software framework behavior adjustment mechanism, peculiar to the general application domain software module bound to the variable point of a software framework, and got the final application system, this process is called software example of a software framework, the existence of software framework allows developers will be the main energy on the development system of the module, so as to improve software productivity and quality.

The behavior adjustment mechanism of the software framework refers to how to adjust the variable part of the framework for the specific application and how to add the method and rules of the specific application module at the variable point.

Ii. Software architecture

Software architecture is a sketch of a system. The objects described by software architecture are abstract components that directly constitute the system. The wires between the components describe the communication between the components explicitly and in relative detail.

Software architecture, by definition, is divided into two camps of ‘constituent’ and ‘decision-maker’, which are described as follows:

The componentized view of software architecture is that the system is described as computing components and their interactions. It has two very obvious characteristics:

Focus on the object of architectural practice — software, with the software itself as the object of description.

This paper analyzes the composition of the software, and shows that the software is not a whole in the sense of “atom”, but a whole composed of different parts connected through a specific interface, which is very important for software development.

Decision-makers believe that software architecture involves a series of decisions, mainly including:

Organization of software systems

Choose the structural elements that make up the system, the interfaces between them, and the behavior that these elements exhibit when they cooperate with each other

How do you combine these elements so that they gradually synthesize into larger subsystems?

The architectural style used to guide the organization of the system: these elements and their interfaces, collaborations, and combinations

Software architecture is concerned not only with the structure and behavior of the software itself, but also with other features: usage, functionality, performance, elasticity, reuse, understandability, economy, and technical constraints and trade-offs.

Personal understanding: When software engineering has a certain scale, software development does not exist in the form of data structure + algorithm, but “divide and conquer” software based on many factors such as technical choices and user needs. The main task of the architect is to divide the software into different modules and define the interfaces between modules.

Sources:

https://softwareengineering.stackexchange.com/questions/229415/difference-between-an-architecture-and-a-framework#:~:text=An%20architecture%20is%20the%20the,that’s%20designed%20to%20be%20extended.&text=Frameworks%20are%20specifically%20designed%20to%20be%20built%20on%20or%20extended.

From the blog haorusong by Unknown and used with permission of the author. All other rights reserved by the author.

What is AngularJS?

In the Software Constr. class, I was presented for the first time with the angularjs front-end web framework. AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML’s syntax to express your application’s components clearly and succinctly. AngularJS’s data binding and dependency injection eliminate much of the code you would otherwise have to write. And it all happens within the browser, making it an ideal partner with any server technology.

I had the chance to work a little with this framework and I understand some part of it how it works. Angular has the following key features which makes it one of the powerful frameworks in the market.

 MVC – The framework is built on the famous concept of MVC (Model-View-Controller). This pattern is based on splitting the business logic layer, the data layer, and presentation layer into separate sections. The division into different sections is done so that each one could be managed more easily.

Data Model Binding – You do not need to write special code to bind data to the HTML controls. This can be done by Angular by just adding a few snippets of code.

Writing less code – When carrying out DOM manipulation a lot of JavaScript was required to be written to design any application. But with Angular, you will be amazed with the lesser amount of code you need to write for DOM manipulation.

Unit Testing ready – The designers at Google not only developed Angular but also developed a testing framework called “Karma” which helps in designing unit tests for AngularJS applications.

There are some advantages for this framework.

Since it is an open-source framework, you can expect the number of errors or issues to be minimal.

Two-way binding – Angular.js keeps the data and presentation layer in sync. You do not need to write additional JavaScript code to keep the data in your HTML code and your data later in sync. Angular.js will automatically do this for you.

Angular can take care of routing which means moving from one view to another. This is the key fundamental of single page applications; wherein you can move to different functionalities in your web application based on user interaction but still stay on the same page.

It extends HTML by providing its own elements called directives.  So why Angular? While AngularJS does not suit every project idea, it builds amazing apps. The most valuable reasons of AngularJS usefulness lie in their concepts and benefits that they provide. Nowadays with all marketing strategies and technologies to find a worth product has become a real challenge. Besides, it is easy to lose yourselves among all those benefits that are listed by every product. And it is even harder to find those ones you really need and that really suits your idea.

From the blog CS@Worcester – Tech, Guaranteed by mshkurti and used with permission of the author. All other rights reserved by the author.

What is the difference between a software framework and a software architecture?

Software frameworks are reusable “semi-finished” software for domains (such as ERP, computing, etc.) that implement common parts of the domain and provide well-defined points of variability to ensure flexibility and extensibility. In other words, the software framework is the softwarenation of the results of domain analysis and the template for the final application in the domain.

With the expansion of software scale, wide application and the development of software reuse technology, the software reuse based on subroutine and class has a lot of shortcomings:

(1) The library of the subroutine is becoming more and more huge, which makes it difficult for its users to master

(2) Most classes are too small to do all the useful work by themselves

It is for these reasons that a set of classes (modules) are considered as a whole in reuse, resulting in a software framework. The software framework contains at least the following components:

(1) A series of modules to complete the calculation become components

(2) The relationship between components and the interaction mechanism

(3) A series of variable points (hot spots, or adjustment points)

(4) Behavior adjustment mechanism of variable point

Developers through the software framework behavior adjustment mechanism, peculiar to the general application domain software module bound to the variable point of a software framework, and got the final application system, this process is called software example of a software framework, the existence of software framework allows developers will be the main energy on the development system of the module, so as to improve software productivity and quality.

The behavior adjustment mechanism of the software framework refers to how to adjust the variable part of the framework for the specific application and how to add the method and rules of the specific application module at the variable point.

Ii. Software architecture

Software architecture is a sketch of a system. The objects described by software architecture are abstract components that directly constitute the system. The wires between the components describe the communication between the components explicitly and in relative detail.

Software architecture, by definition, is divided into two camps of ‘constituent’ and ‘decision-maker’, which are described as follows:

The componentized view of software architecture is that the system is described as computing components and their interactions. It has two very obvious characteristics:

Focus on the object of architectural practice — software, with the software itself as the object of description.

This paper analyzes the composition of the software, and shows that the software is not a whole in the sense of “atom”, but a whole composed of different parts connected through a specific interface, which is very important for software development.

Decision-makers believe that software architecture involves a series of decisions, mainly including:

Organization of software systems

Choose the structural elements that make up the system, the interfaces between them, and the behavior that these elements exhibit when they cooperate with each other

How do you combine these elements so that they gradually synthesize into larger subsystems?

The architectural style used to guide the organization of the system: these elements and their interfaces, collaborations, and combinations

Software architecture is concerned not only with the structure and behavior of the software itself, but also with other features: usage, functionality, performance, elasticity, reuse, understandability, economy, and technical constraints and trade-offs.

Personal understanding: When software engineering has a certain scale, software development does not exist in the form of data structure + algorithm, but “divide and conquer” software based on many factors such as technical choices and user needs. The main task of the architect is to divide the software into different modules and define the interfaces between modules.

Sources:

https://softwareengineering.stackexchange.com/questions/229415/difference-between-an-architecture-and-a-framework#:~:text=An%20architecture%20is%20the%20the,that’s%20designed%20to%20be%20extended.&text=Frameworks%20are%20specifically%20designed%20to%20be%20built%20on%20or%20extended.

From the blog haorusong by and used with permission of the author. All other rights reserved by the author.

DRY (Don’t Repeat Yourself)

https://thevaluable.dev/dry-principle-cost-benefit-example/

I’ve chosen to talk about a very simple design principle this week called “Don’t Repeat Yourself”, DRY for short. It’s a topic that is covered in this class according to the syllabus and I chose it since its similar to another topic I covered YAGNI in that they’re easy to understand design principles. The meaning is quite self-explanatory, don’t repeat code since if you need to change the behavior of a certain project, you’d have to rewrite numerous lines of code if DRY wasn’t applied. However, applying this principle to everything isn’t efficient either. Trying to apply DRY everywhere causes unnecessary coupling and complexity which also leads to more difficulty changing behavior. According to the link above, using DRY means emphasizes knowledge above all else. What it means by that is that when designing and constructing software, one should have the knowledge of when to apply DRY and when not to for the sake of the readability and efficiency of the code.

In that context, DRY reminds me of the importance of resources in a computer when running something. If you want something run faster, you’ll have to sacrifice more memory. And when you want something to have more memory, you’ll have to sacrifice more speed. Both are valid choices; it really depends on the needs of the software and the user. Say for example, I want to create a program that lists all numbers from one to 100 which I do by writing out a thousand lines of code in which each prints a number. However, if I implement DRY, then I could create an integer variable r and a loop which prints the value of that variable and increments it by one until r equals 100. But the case where I want to alter the behavior to list every odd number between one and 100 is where thing get a bit interesting. In the DRYless scenario, I can simply delete the lines of code that print even numbers. Yet in the scenario with DRY, I’d have to add a condition that skips printing variable r for that iteration of the loop. You have to sacrifice complexity for readability and vice versa. Though the choice is ultimately up to what works best in the current situation. Like in my example, the added complexity from DRY doesn’t really harm the readability, in fact it improves it in some ways, at least in my opinion.

From the blog CS@Worcester – Rainiery's Blog by rainiery and used with permission of the author. All other rights reserved by the author.

Object Oriented Programming and Parting Thoughts


While this blog will still be open for the foreseeable future, this will most likely be my last post for some time. This made me think on what would be a fitting final post for this class. After spending the last three posts discussing a pretty involved topic, I figured it would be fitting to take a step back and remind myself exactly what I have been working with for this, and many other semesters. Thus, for this final post, I will be examining Object Oriented Programming as a whole, defining exactly what it is and why it has such significance.

So first and foremost, let’s determine exactly what makes a programming language object oriented. For this week I found an extremely extensive blog post discussing all different components of object oriented programming. I mistakenly assumed that only specific languages, such as Java, could be defined as object oriented, but this concept is not so rigid. This is less of an attribute a language can have and more of a method of programming. It revolves around using classes and objects to represent general ideas that can be instantiated as different instances of objects. Think of it as giving yourself a template within your program that can be reused for others. To specify, this semester we had a program storing different types of ducks with different attributes. In this program you could define a general duck class with all relevant methods and a general duck object with attributes shared by all. Now, when calling this class, you can set unique values for each duck created to represent different types rather than specifying each duck as its own object. This is the general idea, but as always I encourage any readers to refer to my source for a more in depth definition.

So why is Object Oriented Programming significant? If you asked me a year ago I would have said, because my professors talk about it so much. But I have since learned that there are a multitude of benefits that come with this method of programming. This can be summarized in by four specific principles, being inheritance, encapsulation, abstraction, and polymorphism. To summarize, these principles focus on making objects to contain information, only showing what your user needs and hiding other information. Additionally these objects, and their methods, will be able to perform similar tasks and should be accessible by any child classes. These allow for an overall more flexible program, resulting in less work for the programmer without compromising on program complexity or functionality. Often this will allow a complex program to be broken down into more sensible components.

This blog has been fun to post on and, more importantly, has forced me to actually sit down and confront the meanings of some of these more complex subjects. As always, please refer to the source if you want a more substantial walkthrough of Object Oriented Programming, but I hope I could give you the jist of its meaning and importance.

Source:

https://www.educative.io/blog/object-oriented-programming

From the blog CS@Worcester – My Bizarre Coding Adventures by Michael Mendes and used with permission of the author. All other rights reserved by the author.

Design Patterns

Earlier this semester, we worked on an assignment regarding design patterns. I found this interesting as I took a deep dive into learning more about facades. As I’ve gotten deeper into the computer science program, assignments and projects have naturally gotten bigger and bigger. I was excited to learn more about facades, because it relies on two aspects important to large scale projects: simplicity, and restriction. It can make complex projects a bit easier to follow, as well as limiting what a client has access to.

While I learned a lot about facades through this assignment, I felt that I didn’t personally study enough about the other gang of four design patterns. To familiarize myself further that what I learned in class, I listened to episode 34 of the “complete developer podcast”, focused on design patterns. It wasn’t a thorough as I would have liked, but I was able to familiarize myself a bit more on behavioral and creational design patterns. Having studied facades closer, I was already a bit familiar with structural patterns. From their explanation, these 3 types of design patterns have a lot of cross over but tend to be categorized separately primarily for human understanding. I would have liked if they discussed some actual pattens within the creational, structural, and behavioral categories, such as certain ones they use more often than others.

One key takeaway I had with this podcast is how universal these object-oriented design patterns are. One of the hosts was appreciatively saying how he’s a .net developer but could talk to a Java or Ruby developer about any of these design patterns. They may not be familiar with the language, but they would be able to follow the structure of the code. The patterns themselves aren’t that complicated, but they’re capable of facilitating much more complicated programs. I also thought it was interesting, they referenced how some languages don’t need these patterns depending on the level of abstraction built into it.

I found their criticisms of design patterns to be the most useful to me. The hosts discussed certain misusages of design patterns, and these are things I can keep in mind going into the future. In particular, as some programs evolve, they may require a different design pattern than what’s originally implemented. What I take away from this is that it’s important to diagram your project before you get too invested in it. A simple UML diagram can likely show you if you’re using the right pattern, or if you’d need to change as you get further into the project.

From the blog CS@Worcester – Derek's Design by dereksspace and used with permission of the author. All other rights reserved by the author.

Blog #7: Hierarchies

I have already written two separate blog posts on the topic of Class Diagrams (UML and ER) so it only seems right that I revisit how they relate to hierarchies in programming. During this semester, we transitions from UML Class Diagrams into hierarchies with class assignments and a homework project about ducks. The fact that the assignment was based on a program about ducks sounds funny, but it was actually a great example to work with for learning hierarchies better. Some ducks can fly, swim, quack, or squeak depending on the type of duck (including rubber ducks etc.). This is perfect because although all the duck types are considered “ducks,” they all cannot do the same things. This means that programming classes for the different ducks was extremely efficient if it had a good hierarchy for the classes. Rather than hard-programming what every duck could do one at a time, the hierarchy allows the programmer to write much less (as well as have a much easier time adding or deleting duck types). Obviously since all the ducks where considered “ducks” the main class we had to write was just the duck class. Every other class extended off this class and inherited functions from that class. If some ducks shared similar actions and properties, then they would be grouped together under another class and so on. This often creates a web/tree shape if the program where to be drawn out in a diagram. I have learned about hierarchies and their benefits and importance before this semester, but revisiting it is always good for me, especially since I have a bad habit of trying to hard-program things if I am not getting the hierarchy to work the way I want it to. For this post, I did not use a link, but I certainly would still recommend looking around the internet or in books to find all the information about this very important topic of computer programming. All of the studying, researching, and practicing is valuable!

From the blog CS@Worcester – Tim Drevitch CS Blog by timdrevitch and used with permission of the author. All other rights reserved by the author.

Refactoring

No one likes messy code, and everyone likes simplified code, so I was interested in learning more about refactoring. While the idea of enhancing code sounds fairly intuitive, I wanted to learn more about tips and practices to use when refactoring code. In the past, I’ve been guilty of leaving my code in rough shape, until after I finished. While my habits have improved, I still have a lot to learn in these regards. To help learn some refactoring methods and practices, I listened to episode of 78 of Full Stack Radio, with guest Ben Orenstein. Orenstein, dubbed “one of the refactoring guys”, formerly worked at Thoughtbot in Boston, and now offers a course on refactoring, as well as gives lectures on the subject.

What I really liked about this podcast with Orenstein is how direct he was with all his tips. None of his advice sounded complicated, because he used very simple, explicit language. In fact, this type of language demonstrated one of his tips: “make the implicit explicit”. For example, give full words when naming object. If there’s an intermediate equation in the middle of a method, leave comments or naming conventions that clearly state why it’s there and what it leads to. Too often, I’ve used vague abbreviations in my naming conventions. While in most small-scale programs, this isn’t an issue, I realize this could be very problematic on larger projects.

“first make the change easy, then make the easy change.”

One of the best tips I thought Orenstein offered during the podcast was preparatory refactoring, or to refactor code before making changes, rather than refactoring while making changes. In this regard, your preemptive changes can cause you to have to make less changes further down the line. He gave an example of once refactoring code prior to a new feature being implemented. In the end, the new feature was pulled and not implemented, but his refactoring in advance still improved the codes functionality.

I feel like I took a lot away from this, from small tips to things I never thought about. Something that caught me slightly off-guard was when Orenstein talked about not wanting to return null values but replacing them with empty arrays. I don’t recall ever learning about this, and they didn’t go into much detail about it, so I researched it a little further on my own. This podcast helped highlight the importance of refactoring and I’m sure I’ll continue to research more refactoring methods throughout my career.

https://fullstackradio.com/78

From the blog CS@Worcester – Derek's Design by dereksspace and used with permission of the author. All other rights reserved by the author.

It’s Easy to Break Promises

Context

I’m currently writing a Node.js package for a wrapper I’m calling a curfew-promise. It’s simpler than I thought, but it is still worth doing in my opinion. The package exports a single function that returns a promise. The promise has “3” parameters with the function header being: (curfew, func, ...args). The promise then performs func asynchronously (so func itself can be sync or async). It passes ...args to that function when it’s called. Lastly, the key idea here is that if func takes longer than curfew milliseconds to complete, the wrapper will become a rejected promise.

At first, it seemed like a tough task, until I discovered the built in Promise.race() function which creates a promise which we can refer to as the racePromise. That function then also takes in multiple other promises. Whichever passed in promise resolves or rejects first, its value is then passed onto racePromise. I can achieve my curfewPromise then by creating one promise that runs func and one that rejects after curfew has passed. Whichever finishes first becomes the value of the promise the function returned. The only way I’ve found to pause an async operation in JavaScript is via await new Promise((resolve) => { setTimeout(resolve, duration); }); This line, when placed into any async function, will pause operation until duration has passed. You can also remove the redundant brackets and shrink it down to await new Promise(r => setTimeout(r, duration)); , but I prefer to be more consistent.

JavaScript is NOT Multi-Threaded

JavaScript runs in a single thread. The way it pretends to be multi-threaded is by switching back and fourth between tasks to give all of them a little bit of time until they all finish. JavaScript is also an interpreted language. This means while trying to test my package, I had a lot of trouble. I spent a few hours trying to understand what was going on and now that I have, I’m going to write about it to save you trouble.

The Code

I was completely convinced that JavaScript itself was just broken. Here is my package, at least in its current state: (If you’d like to use this or see the modern version, check the GitHub page (soon to also be on npmjs.com))

module.exports = (curfew, func, ...args) => {
    let waitId;

    async function wait() {
        await new Promise((resolve) => { waitId = setTimeout(resolve, curfew); });
        return Promise.reject(new Error("Curfew of " + curfew + "ms have elapsed."));
    }

    async function perform() {
        const value = await func(...args);
        if(waitId) clearTimeout(waitId);
        return Promise.resolve(value);
    }
    
    return Promise.race([wait(), perform()]);
}

wait() creates a promise (using async notation, since from what I’ve read that is more ideal than direct promise notation) which waits until curfew has passed, which then rejects with a useful stack trace message. You’ll notice I’m also storing waitId, which is the ID of the setTimeout call. This way, if func finishes before curfew, I can cancel the timeout and not waste performance. I’ll also be looking into ways to create cancellable promises. I’m aware there are already packages that do this, but I think I’ll benefit from doing it by hand. I could make wait() a synchronous function that simply returns a waiting promise that calls setTimeout for reject, but I chose making it like this because then it matches the form of perform() (two async functions), and it allows me to write two lines that are visibly neat rather than trying to force everything into one line.

perform() creates a promise that waits until func is finished. Once it is, it’ll attempt to stop the waiting promise. If the promise is still waiting, it’ll stop it. If the promise has already rejected, it will do nothing. Then, the function returns a resolved promise with the value from func. I chose to write return Promise.resolve(value) instead of return value, which I understand to be the same thing, for consistency once again, and I think it makes the code more readable overall.

Lastly, I am creating the promises off of these functions and making them race. The function returns a promise that resolves or rejects whenever the first of the two – wait() and perform() – finish.

The Problem

I was able to narrow down the problem to this line:

        const value = await func(...args);

All of my tests had worked until I did something like the following:

const curfewPromise = require("./index");

// Broken Promise 1
console.log(curfewPromise(10000, async () => { 
    for(i = 0; i < 1000000; i += .001);
}));

// Broken Promise 2
console.log(curfewPromise(10000, async () => { while(true); }));

I found that for broken promise 1, despite the fact that curfewPromise returns a promise, it wouldn’t finish until the for loop finished. Even if I set the curfew to 0, it would take until the for loop completed. Broken promise 2 would never even end. I purposefully wanted to test these edge cases, where something would actually take a long time for ever (a good example for why I want the ability to cancel a promise).

The problem that I realized so frustratingly last evening is, and say it with me, JavaScript is NOT multi-threaded. Yes, when you run an asynchronous function, you can do other things in the meantime while it finishes. But as far as I can tell, JavaScript does this on a line by line basis. If you have a single line that is very slow or infinite, JavaScript will start running it, as that’s how asynchronous functions work, and then after some progress, it will move on. The thing is, you can’t make progress until that line ends. In the case of an infinite while loop, it will never end. In the case of a very slow one-line for loop, it can’t move on until the for loop is finished. Promise.race() cannot return a promise, so curfewPromise cannot return a promise. Once the for loop actually ends, it’s a gamble to decide which non-neutral-state promise will be chosen to have won the race. (Also keep in mind when using very small curfews, there is internal delay and it may not behave how you expect).

Conclusion

JavaScript is not multi-threaded. Make sure you keep that in the back of your mind. I was inadvertently testing for a case that shouldn’t ever even happen. While it was frustrating trying to figure out what was wrong, I still think that this kind of struggle is necessary in both life and learning. I always learn the most in coding when I’m trying to find out how to do something and I have 20 tabs open.

While this is a simple package that does something many developers probably can do easily, I still want to spend time making it and even upload it to npm. I think even though it’s simple, the function still helps clean up syntax to improve readability and reduce lines. I also think making it an external package helps to reduce complexity in your projects and helps me use it in multiple projects. Maybe someone can also look at it for help when learning how promises work.

At the end of the day, promises and asynchronous functions are an incredibly valuable tool in JavaScript and the illusion of multiple threads helps in most situations. Just be careful to not break your promises.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Blog #6: Design Patterns

The class that I am taking right now goes over database design patterns, so it is only right that I research even more about them for this most recent blog post. I found an incredible website that discusses all sorts of designs, some which that I have never heard of before this. I will attach the link to the website but it was from sourcemaking.com. The examples that the website describes all fall under three different categories: creational, structural, and behavioral design patterns. The creational design patterns are defined as being all about instantiation. There are other subclasses of this design pattern group like class-creational and object-creational patterns. Some examples from the website of patterns in this larger group are builder, singleton, factory method, and more. In contrast, the structural group of patterns are all about class and object composition. Some examples of patterns from this group are adaptor, composite, bridge, decorator method, and more. The last group, behavioral, is defined as patterns for Class’s objects communication. These patterns are mostly concerned with communicating with objects. Some examples of this design pattern group are command, iterator, observer, visitor method, and more. I am very happy that I went back and revisited this topic from my class, especially since I am about to take the final in this class. I recommend taking a look at the same website that I used to research for this blog post, and I genuinely wish I found it earlier in this semester!

https://sourcemaking.com/design_patterns

From the blog CS@Worcester – Tim Drevitch CS Blog by timdrevitch and used with permission of the author. All other rights reserved by the author.