I wrote a Stenciljs component "textarea" with a lot of methods and logic. Additionally I need an inputfield with pretty much the same functionality but some minor differences. I don't want to maintain two components that have nearly the same tests, nearly the same styles and nearly the same methods that would end in a lot of code duplicates.
Right now i created a generic component "idb-input" with a "type" property that can be "textarea" or "textfield" and use if else statements to decide which methods are allowed for this type. Since this is a bit messy i would like to have a "base component" and inheritate from it for example. I already tried to use a generic typescript class but i can't use the decorators and a lot more limitations.
Further this approach isn't that clean in HTML:
<idb-input type="textarea">
<idb-input type="numberfield">
<idb-input type="inputfield">
What is the right way solving this problem?
Related
I understand that reactivity is a big deal in VueJs. However, I tend to use OOP for my front end development, and therefore data is often provided by functions. This will be naturally non-reactive, which can be overcome by using this.$forceUpdate.
The question is - is this a fundamentally bad concept? Or is it just fine? Is there a better way? Probably watchers can be used, but I feel like that would make the code more complicated.
Example:
<template>
<multiselect
:value="myclass.getValue('param1)" />
#input="val => valueUpdated(val)"
</template>
Then in methods:
valueUpdated(newVal)
{
this.myClass.setValue(newVal);
this.$forceUpdate();
}
Note, myClass has async data, so by the time of the first rendering, it is not filled with the data. MyClass comes into the component as a prop, and it is a TypeScript class.
this solution works fine, but is there a better (correct) way?
Doing/forcing view to update manually is a fundamentally bad concept. The view should update at the moment your data changes - and it should update automatically. This is what reactivity gives you. This is like going from a car with manual gears and 49 shifts to a car with automatic shifting.
The whole idea is that you define declaratively the behavior of your view - how it depends on the data model. Building the view imperatively is more tedious and error-prone and certainly less elegant.
OOP may work well in non-visual libraries - but for UI composing components with props and events works better.
I have a class design that looks like this one:
When Main receives an item, properties of other items can change based on some rules. For example, if Item1 has a red color, item2.level must be 3. Sometimes a value can change properties of multiple items. Implementing all rules in Main class is possible but it's a mess code.
So, I have implemented the Aggregate class that include all items. When Main.setItem(item1) is executed, I update Aggregate with Aggregate.setItem1 and run Rules.updateAggregate that updates items of Aggregate according to all rules.
It works, but Rules class is very inefficient. Because it doesn't know which item has updated, it apply all rules all times. Also, updateAggregate method is very large and difficult to test.
Is there any better design?
To reduce the coupling you could use a design based on events.
Main and Item classes should be publishers of events and Item classes should be also subscribers of event types as they want to react to events.
You should define some event types. For example :
event type : "new Item with ..."
event type : "Item 1 changed the foo property"
and so for...
According to question and comments, here is one example of a design that could work. Gist link to the example code
The example is made using C# but should not have any problems to implement other languages. (Could be easier with dynamic languages)
The design probably doesn’t fit directly to your use case but here are a few points what I try to demonstrate with it and maybe you can find better ideas with this way.
I made a few iterations and this was the first version that I could work on a similar use case without any third party libraries.
Main points of design
In the example, I try to keep Item -classes very clean from rules.
Rules -class is disappeared because, in the example, rules are in Aggregate class. However, I don’t see any problem to implement the same rules in separated Rules class, if needed. I don’t know exactly how complex your rules are and tried to keep the example simple.
The aggregate has methods to raise “notification” about Item changes.
I didn’t test my example but the implementation should be easier to test. For example, you should be put Items on specific state and try how rule behavior works. This can be validated to use unit tests but I didn't have any real use cases.
I tried to kept classes decoupled as possible.
Downsides
Depending on your needs, classes can be too coupled. Specially Aggregate can contain a lot of code so the more decoupled solution should be possible.
Implementation can be varied by programming languages and not always so clean. Originally, I used a similar pattern with event sourcing and modified to this example.
If a number of Items are huge, then the design is not very flexible.
How to improve
As said in comments and other answers, event-based implementation is probably what you want. I used Observer pattern as a starting point but it was going towards event-based implementation.
You should also look at some event-driven libraries that can have a good example of how to implement an application that reacts to changes. Also, those libraries usually help to wire up objects and give more decoupled implementation. Of course, then you are coupled with those libraries but probably not a bad case. No need to reinvent this mechanism anyway.
Check following links that can help with new ideas. Observer vs pub-sub pattern
I completelly agree with #davidxxx that events based design is better approach in your case. You can have a look at the observer design pattern. In case your business logic is so complex that you are not able to provide reqired parameters , you can always inject the whole list/tree/whatever of items and perform find operations on it.
So I believe the title introduces my question. Given you're introducing a new dependency in each component you want to use mapGetters in, this adds bloat to your package.
This also means your component is now specifically bound to Vue, which is 1 more thing to contend with were you to port components over to another framework like React.
Consider these 2 computed property lists:
import { mapGetters} from 'vuex'
computed: {
...mapGetters({
active:'interface/active',
mode:'interface/mode',
views:'interface/views',
}),
}
vs
computed: {
active:() { return this.$store.getters['interface/active'],
mode:{ return this.$store.getters['interface/mode']},
views:{ return this.$store.getters['interface/views']},
}
Sure the latter is a tad bit more verbose, but nothing overly bad. You've still got all your getter data the same way in either scenario. To be this seems like totally unnecessary fluff for the small benefit of saving a few characters.
The former example weighs in at 207B (201 characters)
while the later example weights in at 207B (201 characters).
To me that means in terms of type savings, there's virtually none to be had. However I do concede that the former is more readable, portable and ultimately easier to maintain as your relevant data is all in 1 spot.
There are a couple of things that I think are worth mentioning here, regarding an opinion you have on the helper function like mapGetters
About your code being tightly coupled to vuex should you decide to import mapGetters: it should be clarified that the approach where you access this.$store.getters directly doesn't make your code any less coupled to vuex. After all, such direct access already does assume quite a lot about store's functionalities and how they're exposed to components.
Take snippets you provided as examples, it can already be seen that your store implementation a) has a concept called getters, and that b) it supports modules such that you can define an interface module like you did.
Suppose one day, you somehow decide to switch store's implementation to something like puex, which has absolutely no concept of either getters or modules, you will have to refactor all 3 declarations anyway. Or even if you decide to switch to something more advanced like Flure, it will also put you in a similar situation: though Flure has concepts of getters and modules, they aren't exposed the same way vuex does, so you have to edit all 3 lines (again).
Let alone porting to React, the code you have in computed properties won't even be portable to other store libraries created specifically for Vue. So, really, you shouldn't worry too much about using mapGetters.
Secondly, for type-saving sake, if you're not going to rename these properties anyway, your mapGetters call can actually be shortened to a one-liner:
computed: {
...mapGetters('interface', ['active', 'mode', 'views']),
}
Third, once you start having multiple lines of these, it's just easier to track all declarations (e.g., how many getters or state fields you expose from each module). So these helper functions actually helps improve maintainability if used well.
computed: {
...mapState('interface', ['list', 'packages']),
...mapGetters('interface', ['active', 'mode', 'views']),
...mapGetters('foo', ['bar', 'baz']),
}
Forth, regarding bundle size, on second thought I believe this might be the main reason why people downvoted you. So, I'll try to explain:
The thing you need to understand is that real-world production webapps these days use build tools like webpack to create javascript bundles. And because of that, javascript you wrote can be pretty much regarded as source code, which is totally different from the code shipped in a bundle. The reason why they are so different is that the bundle can utilize both minify and gzip techniques to achieve drastic improvement in file size (usually more than 70% size reduction in practice).
In other words, for webapps these days, javascript is not being served as-is, but almost always be processed by webpack or the like. So, all the character counting you have been doing on the source code isn't going to make a noticeable difference to the final bundle size at all. And because of this, some people might regard your concern as an extremely bad form of micro-optimization, hence their downvotes.
If I were you, I will try to embrace these helper functions as much as possible, and look at the bundle size after automatic build optimizations before worrying about the bundle size at all. And even if the final bundle size is too big to your liking, I can almost guarantee you won't gain much from mapGetters refactoring, as it's usually other stuff that substantially bloats the bundle size (like a view component library, for example). Really, premature optimization on vuex isn't really worth your trouble.
So, to me, these functions (mapState, mapGetters, mapActions, mapMutations) are definitely worth using.
What are the PROS and CONS on using onePageObject class for storing my all xpath/css selectors and etc., and then use them in other page object methods.
I'm thinking how lower the needless xpath's that are constantly is repeating in different pageObjects class.
Any suggestions?
Somebody already doing this? If yes, is it easyer or harder to find what you need?
I'm thinking to use the code something like this:
ObjectClass.java
Public class ObjectClass myXpaths {
#FindBy(xPath);
private button xPathButtonAdd;
#FindBy(xPath);
private button xPathButtonDelete;
#FindBy(xPath);
private button xPathButtonCancel;
}
ObjectClass2.java
import ObjectClass;
Public class void ObjectClass2 myPageObject {
ObjectClass smth = new ObjectClass();
smth.xPathButtonAdd.click();
smth.xPathButtonDelete.click();
smth.xPathButtonCancel.click();
}
CONS as I see it:
One huge class of selectors - huge classes are typical code smell.
Other page object class would inherit from or initialize an object
with a lot of selectors it doesn't need.
Violation of Single Responsibility Principle (SRP).
PROS:
Avoiding some repetitive code - you could avoid it by other means
(see example bellow)
....
If the reason why you think of doing this is minimizing repetitive code, you should rather think of how to extract that repetitive code to separate classes. For instance, given a application with multiple pages where every page has standart search section, you can extract it to separate class SearchSection or SearchBox and use it in pages where you need it.
If you gave an example of repetitive code or what do you want to do, it would be easier to suggest something.
Ok, I think I get now where you want to go. I would definitely recommend separating the selectors from the actual code. We organize our page objects in classes that more or less represent one screen of the application under test. Those classes are then again in a structure of packages representing the business process that is tested. That way we can easily reuse page elements and if something in the application under test changes we only have to touch this "repository" of page elements but not the script that does the action. We also use prefixes like "link", "button", "input" and so on that indicate the type of page element so that the action code is easier to understand and read.
But I would really advise against throwing all in one huge class, because you might have trouble finding things later on. :-)
I'm not much of a web designer or programmer, but I seem to run into this issue with CSS classes: what's the best way of managing sets of CSS classes that share attributes in common?
For example, I'm currently working on an application with a status bar representing the status of a file transfer. It's used in three different locations, each of which is a different size. In addition, if the transfer fails, the bar should be a different color.
What's the best approach, in general:
Add "statusbar" and "transfer-failed" classes to the divs independently, and check for their combined existence?
Have "statusbar" and "statusbar-failed" classes, set the class appropriately, and use careful CSS structuring to avoid repeating code.
Have a "statusbar" class, then use context like the div being inside a "summary" table or a "transfer-failed" div to further specialise it.
Are there any general rules? Approach 3 seems fragile, because changing the name of a seemingly unrelated class could break stuff. Approach 1 feels strange somehow, having classes like "failed" that would be meaningless without another class, and could also mean different things in different contexts (eg, "failed" could also be applied to a failed form validation...) Approach 2 sometimes gets unwieldy, with lots of very specific classes with long names.
If there will always be only one "status bar" feel free to use an
id instead of a class for it.
If there will be multiple on the same page, and they look
anything alike, stick with class.
Assign a transfer-failed class when appropriate. In in your CSS,
under this class, should only have the properties that
differentiates it of the default "status bar". Personally, I like #3
(the context approach). WordPress and other CSMs assign the page
name and category (and anything else you'd like) as <body>
classes. Modernizr uses the <html> tag. More info here: http://perishablepress.com/dynamic-body-class-id-php-wordpress/
#Lokase's SMACSS is great. For more tips on organizing your CSS, check this out: http://coding.smashingmagazine.com/2007/05/10/70-expert-ideas-for-better-css-coding/
Take some time to look at a few CSS methodologies or frameworks, I am a fan of SMACSS
There are a lot examples of best practices out there, you just have to find them and go through the learning curve.