code analysis could give some statistic numbers, which are not determinant, but good to start with, if you are looking at some design defect or bad coding practice.
such KPIs could be how many methods in a class, or how may levels of if/else used...
is there some code metrics for MVVM program?
for example, one thing i noticed in one of our last project is, each class sounds not big, but there's a tree that make the possible workflow very complex:
ViewModel Command => Business Method => ViewModel Properties => ViewModel "Navigation Properties" (hidden/shown/collapse/expand)
Note: I call it "Navigation Properties" as the whole MVVM project's navigation is based on MVVM binding, but setting some VM properties as hidden/shown/collapse/expand, the GUI is navigated.
is there some special design "trap" that MVVM might fall into, and KPI's to watch that?
As a general habit, I like to run "Calculate Code Metrics".
(right click on the project and select Calculate Code Metrics in visual studio 2010)
The maintainability index and clyclomatic complexity scores give you some indication of KPI.
With MVVM, even if your "tree workflow" is longer, it will be simpler than through other mechanisms if done right. I would suggest that most of the time, the tree will be shorter in MVVM as well.
Having said that, generating a lot of events can cause your app to slowdown, so it is good practice to only use raise the "property changed event" when the property has a change of value ( explicitly check it is different in your property setter )
Related
I'd like to define an enum (or something) to give names to possible values of seletedIndex and define the order of destinations in, say, a Flutter NavigationBar in such a way that I only have to go to one place to change the order of the destinations.
The examples I've seen so far always require reordering be done in two places: one in the list of destinations given to the NavigationBar that have an implicit, invisible, unnamed index, and the other is a switch or a subscripting based on selectedIndex to establish the selected page. This seems like a bug magnet. Is there any way to set it up so I only define the order of the destinations in one place and have the list of destinations bound to the correct pages?
It seems to me that NavigationDestination should have a property to handle this binding or a "displayOrder" property, but I don't see this. If there isn't a better way, I guess I could write a function to construct the destination list based on an object (like an enum) that binds the numeric indicies to the corresponding page view, but this seems like a lot of machinery to create for a routine navbar task, especially in this modern OO context -- weird that selecting navbar pages would need a switch in the switchless programming world. Yet the example implementations have switches and two separate areas of the code need to be maintained to do one thing. But, what do I know; obligatory newbie disclaimer follows...
I think my question above was poorly phrased, based on ignorance and seeing some naive examples that suggested page navigation was generally done with an integer like selectedIndex. Once I learned about the Navigator class, and other navigation and List related builders, I saw the OO techniques Flutter provides for putting together hierarchical menus and such without the use of switch statements and integer indicies. So my answer to somebody like me who asks "do I really need to re-invent the navigation wheel" is to learn about Navigation Basics first.
I'm new with GWT and recently I've added Actvivities, Places and ActivityMappers to my code. I have one ActivityManager-ActivityMapper per each region. Regions like the header or the menu dont't change a lot so I have to write a lot of boilerplate code in the ActivityMapper for load the same Presenter every time but with a different constructor. For every possible Place I have to write another constructor for the Presenter in order to take the instance given by the ActivityMapper. There's any way to do that easier? Moreover, I'm not happy with the idea of creating a new Presenter every time that we move to a new place(even if you are going to load the same Presenter). In fact I have a big problem with that, cause my activities never die and they keep receiving events.
When an ActivityMapper returns the exact same Activity instance (reference equality, i.e. ==, not equals()) as previously, then the activity is not restarted, and the region is not touched. This is a deliberate optimization for those cases of regions that don't change often (e.g. headers or menus, or a master region in a master-detail setup). This is also the reason for the CachingActivityMapper (and FilteredActivityMapper, specifically designed to be used with the CachingActivityMapper in a master-detail setup)
In your case, it seems like you're imposing a rule to yourself that makes it hard for you to take advantage of this optimization: you're passing the current place to your activity's constructor, for no apparent reason.
(note: names were changed to protect the guilty)
So, let's say I am doing modifications in VisualCruft 8 (long since discontinued by the vendor), and applying those modifications to ERP software from "Company A" (long since bought out by "Company S", who then discontinued the software a few years later due to VisualCruft being discontinued itself).
One of the modifications I frequently need to do is to add, change, or remove fields to a form. This is the bread-and-butter of most ERP software and shows up several times a year. The layout of our ERP package, we'll call it "HotPockets Version 3", divides the forms into "class libraries" that in turn are just buckets to hold the form objects proper; and of course, there are "control" objects embedded inside the "forms".
With each install of HotPockets 3 you get the system version of the form, and a child version in a separate class library that is just a re-class of the parent, so that the forms, controls, business logic, etc. are all present in the child. The intent, as stated by the original ("Company A") vendor, is to allow you to make changes to the child that override the parent, while allowing said vendor to release patches/changes/whatever into the parent. In theory this looks great. In practice, there are issues. Specifically, how does one remove or change a control on a form, when the control itself is defined in the parent, and the parent is not to be changed? The intent is to replace a control with a different control that has different behavior, although in some cases I have also had to remove a control altogether. So, you could also ask this as "How do I remove an inherited object from a child without altering the parent"?
There are some known solutions to this, but I am asking the question because I want to see if there is a better answer than what I will provide. To avoid duplicate answers, I will list the currently known solutions, but keep in mind, I am looking for what is not listed here.
Improper Solution 1
While I am not supposed to modify the parent, I do have access to the parent code. I can simply note all of the properties and methods for the control in question, delete the control from the parent, then go back into the child and re-implement all of the properties and methods. For drastic changes, such as replacing a single text box with a grid of something, this is doable. It is, however, completely "against the rules" and the VAR that provides support for this product kinda frowns on it (note: the VAR is NOT "Company A" or "Company S"). Do keep in mind that not only is the original vendor defunct but the product and the language are defunct as well.
Improper Solution 2
"Hide" the component on the parent form, then (if incorporating a new component) add the new changes to the child. This sounds great in practice, until you realize that all of the old code hooks into the parent, which is now...invisible. Which means renaming the parent's version of the component, and going through all of the "port the properties and methods" listed in Solution 1. In which case...why am I doing this again?
Improper Solution 3
For those instances where I want a control to go away, I can hide the control in the child by setting the visibility property. This does not remove or alter any existing code, and everything continues to function. However, the control and the database field bound to it are now "tied up" and unavailable unless I look at something like Solution 1 or Solution 2, because any attempt to mess with the control will possibly result in side effects during calls, and/or replacing data underneath the control programmatically makes it impossible for the user to observe what is happening. And this only addresses the control visually going away - it does not address replacing it.
Extremely Improper Solution 4
Damn the torpedos, delete the control from the parent, full steam ahead!
Obviously, this is a very bad decision...
You'll note that all of the solutions involve touching the parent, something that I am not supposed to do - which brings us full circle to the question.
Other Solutions Not Available
Replace HotPockets Version 3 with something else. This is not in the realm of my decision making.
Rewrite whatever I need for HotPockets Version 3 with (insert favorite pet language here). While I would not mind doing this - I do have my own pet languages like most folks - it's not a possibility because VisualCruft pretty much works with just itself. Trust me on this, it's about 10x more effort than it is worth to write an extension in VisualWidget 3.14159 or HeyDoYouSmellCoffee or even ILikeSnakes, figure out some kind of cross-language calling, integrate it, test it, get IT management to sign off on it, get the VAR to also sign off on it, than it is to just stick with the native tools in VisualCruft.
Have the VAR do it. Don't take it the wrong way, the VAR does a good job providing ongoing support and has provided lots of useful modifications. But there are cost-factors that play into this, and it's more cost-effective if the changes were made by me, rather than the VAR. This has nothing to do with them at all.
First let me say that from my point of view it is not so easy to quickly get what your question is.
With each install of HotPockets 3 you get the system version of the
form, and a child version in a separate class library that is just a
re-class of the parent, so that the forms, controls, business logic,
etc. are all present in the child. The intent, as stated by the
original ("Company A") vendor, is to allow you to make changes to the
child that override the parent, while allowing said vendor to release
patches/changes/whatever into the parent. In theory this looks great.
In practice, there are issues.
>In theory this looks great.
No it does not! Inheritance is the strongest relationship two entities (aka classes) can have. That is why it has been proposed by Gamma in 1994 and it is widely agreed that:
Favor delegation over inheritance!
Delegation is far more decoupled then inheritance. In your case e.g. you could create a key-value store for your customers custom form fields.
However from your question it is not clear to me if such a change is within your field of responsibility.
But this is the source of all the "evil" you are describing.
Further on my impression is within your question you mix up a parent-child-relationship within the class structure at design time and a parent-child-structure of a tree-like class-composition of the objects-structure at run time.
Think of it this way: Your classes are File and Folder, and Folder can contain Files... By this you can create arbitrary tree like structures at runtime. This is called the "Composition Design Pattern". If you are not aware of it you will get lots of information on the net.
Finally within your bounty you are proposing
that this is a limit of the OOP paradigm
.
IMHO it is not - it is a serious flaw in the design due to a clear misuse of inheritance.
So back to your question:
How do I remove an inherited object from a child without altering the parent?
At design time or at run time? (You can not alter a inheritance at run time)
Remove the inheritance completely at design time.
The question "How do I remove an inherited member of a child" in and of itself is incorrect. I actually know what you mean in this context. However, your wording for the question is basically asking something impossible. If you are creating a parent-child, is-a, inheritance chain between two types, you are assuming one is a more specialized form of the other. If you ever think that human may someday evolve so much that it would have nothing in common with "animals", you should never inherit "human" from "animals". Let's remember that inheritance is as coupled as it gets between classes.
I think Martin is correct in stating that this is not really a limitation in the OOP paradigm. Surely "Hot Pocket" designers knew what type of modifications their users should be able to do when they used inheritance for the child classes. They definitely wanted to "allow" certain changes and "disallow" certain other changes. For example they wanted you to be able to change the behaviour of a control but not be able to remove it.
Having said that, if you do not agree and believe that adding or removing controls is definitely something "Hot Pocket" designers had in mind, then they should have also provided you with a means of doing just that.
All in all, there are three possible scenarios:
-A "Hot Pocket" designers actually give you a way to achieving
this(which obviously wouldn't have led to your question here).
-B "Hot Pocket" designers messed up. They didn't have a clue a user may need
to delete a control in a child class.
-C "Hot Pocket" designers knew
what they were doing. They don't want you to be able to add or delete a control
to the child forms.
In Case A), we already have a solution. Just as the "Hot Pocket" people.
In case B), as it is their fault they can't frown on you having to change the parent because otherwise you have no "good" choice.
In case C), you either submit to the limitation or as in your case, you are forced to change the parent although that is not supported. Of course, that would cause frowns and come with its caveats because you are going against the design.
This is getting longer that I intended, I finish with maybe one more solution that you have not added.
Given the fact that you have no way of "deleting" an inherited member, maybe a better approach than changing the parent would be actually adding a new parent for your special case. If you need to remove a control, in a new copy of the parent make your changes and have the child inherit from the new parent class. By doing this you are actually extending the framework rather than changing it. Maybe this would cause less frowns?
All the GWT / MVP examples I've learned about seem too simplistic to give a clear view what best practises are regarding displaying and handling slightly more complex model objects.
For example, most examples are something like a presenter that attaches a click handler to a few TextBoxes on the view...if save is clicked, the presenter's save() is called which simply gets the updated values, and we're done, MVP style. That's not so realistic though.
For example, let's say we have:
PresenterX
- gets a 'model' object, let's say any object with an unknown number of various primitives or whatever
ViewX
- should show the model object in a table, and/or allows it to be edited/re-saved
...so that sounds very, very basic. But, we don't know the amount of fields in the model object that we will need to display. So that might relate to a dynamic number of rows/columns. Probably no problem for a table...but how should the presenter give this to the view's table? As the model object that the view understands, or break it down into a bunch of Lists...that the view essentially still has to understand.
Also, certain fields might be editable, of which are unknown until we get the model object (something in the model determines what fields are editable, say) -- so who should be responsible for figuring out what is editable or not? Probably the presenter, but how do we refelct that in the view, the MVP way?
Lastly, let's say there's a 'save' button on the view...who's job is it to figure out all the rows in the table which were changed?
Seems to me that the view either needs to understand the model more, or the presenter needs to really understand the view more -- neither of which are nice MVP :( ... Or perhaps there should be some intermediary object.
I know there are some nicer/newer helpful ways for this kind of stuff (Editors/RequestFactory, etc.), but I'm looking for suggestions on the above scenarious.
As I understand it, MVP is a line with M-P-V points. So P interacts with both, but M and V only with P.
Also, one of design objectives of MVP is to have a testable P and M, which means that V must be replaceable with a mock version. So, V should not expose any implementation-dependent interfaces (e.g. HasClickHandlers instead of Button).
Now, if V should show generic table, you should create generic methods: addColumn(..) to define columns and addRow(..) to add data. The new CellTable is pretty flexible and supports adding columns dynamically.
About changes - V should notify, P should act. Also, there are the new Editors, which IMHO do not fit nicely into MVP, but are supposed to be easy to use.
I am battling to understand why a post compiler, like PostSharp, should ever be needed?
My understanding is that it just inserts code where attributed in the original code, so why doesn't the developer just do that code writing themselves?
I expect that someone will say it's easier to write since you can use attributes on methods and then not clutter them up boilerplate code, but that can be done using DI or reflection and a touch of forethought without a post compiler. I know that since I have said reflection, the performance elephant will now enter - but I do not care about the relative performance here, when the absolute performance for most scenarios is trivial (sub millisecond to millisecond).
Let's try to take an architectural point on the issue. Say you are an architect (everyone wants to be an architect ;)
You need to deliver the architecture to your team:
a selected set of libraries, architectural patterns, and design patterns. As a part of your design, you say: "we will implement caching using the following design pattern:"
string key = string.Format("[{0}].MyMethod({1},{2})", this, param1, param2 );
T value;
if ( !cache.TryGetValue( key, out value ) )
{
using ( cache.Lock(key) )
{
if (!cache.TryGetValue( key, out value ) )
{
// Do the real job here and store the value into variable 'value'.
cache.Add( key, value );
}
}
}
This is a correct way to do tracing. Developers are going to implement this pattern thousands of times, so you write a nice Word document telling how you want the pattern to be implemented. Yeah, a Word document. Do you have a better solution? I'm afraid you don't. Classic code generators won't help. Functional programming (delegates)? It works fairly well for some aspects, but not here: you need to pass method parameters to the pattern. So what's left? Describe the pattern in natural language and trust developers will implement them.
What will happen?
First, some junior developer will look at the code and tell "Hm. Two cache lookups. Kinda useless. One is enough." (that's not a joke -- ask the DNN team about this issue). And your patterns cease to be thread-safe.
As an architect, how do you ensure that the pattern is properly applied? Unit testing? Fair enough, but you will hardly detect threading issues this way. Code review? That's maybe the solution.
Now, what is you decide to change the pattern? For instance, you detect a bug in the cache component and decide to use your own? Are you going to edit thousands of methods? It's not just refactoring: what if the new component has different semantics?
What if you decide that a method is not going to be cached any more? How difficult will it be to remove caching code?
The AOP solution (whatever the framework is) has the following advantages over plain code:
It reduces the number of lines of code.
It reduces the coupling between components, therefore you don't have to change much things when you decide to change the logging component (just update the aspect), therefore it improves the capacity of your source code to cope with new requirements over time.
Because there is less code, the probability of bugs is lower for a given set of features, therefore AOP improves the quality of your code.
So if you put it all together:
Aspects reduce both development costs and maintenance costs of software.
I have a 90 min talk on this topic and you can watch it at http://vimeo.com/2116491.
Again, the architectural advantages of AOP are independent of the framework you choose. The differences between frameworks (also discussed in this video) influence principally the extent to which you can apply AOP to your code, which was not the point of this question.
Suppose you already have a class which is well-designed, well-tested etc. You want to easily add some timing on some of the methods. Yes, you could use dependency injection, create a decorator class which proxies to the original but with timing for each method - but even that class is going to be a mess of repetition...
... or you can add reflection to the mix and use a dynamic proxy of some description, which lets you write the timing code once, but requires you to get that reflection code just right -which isn't as easy as it might be, especially if generics are involved.
... or you can add an attribute to each method that you want timed, write the timing code once, and apply it as a post-compile step.
I know which seems more elegant to me - and more obvious when reading the code. It can be applied even in situations where DI isn't appropriate (and it really isn't appropriate for every single class in a system) and with no other changes elsewhere.
AOP (PostSharp) is for attaching code to all sorts of points in your application, from one location, so you don't have to place it there.
You cannot achieve what PostSharp can do with Reflection.
I personally don't see a big use for it, in a production system, as most things can be done in other, better, ways (logging, etc).
You may like to review the other threads on this matter:
Anyone with Postsharp experience in production?
Other than logging, and transaction management what are some practical applications of AOP?
Aspect Oriented Programming: What do you use PostSharp for?
etc (search)
Aspects take away all the copy & paste - code and make adding new features faster.
I hate nothing more than, for example, having to write the same piece of code over and over again. Gael has a very nice example regarding INotifyPropertyChanged on his website (www.postsharp.net).
This is exactly what AOP is for. Forget about the technical details, just implement what you are being asked for.
In the long run, I think we all should say goodbye to the way we are writing software now. It's tedious and plainly stupid to write boilerplate code and iterate manually.
The future belongs to declarative, functional style being held together by an object oriented framework - and the cross cutting concerns being handled by aspects.
I guess the only people who will not get it soon are the guys who are still payed for lines of code.