I have the following code:
public class Character
{
public Vector2 WorldPixelPosition
{
get { return Movement.Position; }
}
public Vector2 WorldPosition
{
get { return new Vector2(Movement.Position.X / Tile.Width, Movement.Position.Y / Tile.Height); }
}
public Vector2 LevelPosition
{
get { return new Vector2(WorldPosition.X % Level.Width, WorldPosition.Y % Level.Height); }
}
}
Now somewhere else in my code, I make about 2500 calls in a loop to Character.LevelPosition.
This means that per update-cycle, 5000 'new' Vector2s are being made, and on my laptop, it really drops the framerate.
I have temporarily fixed it by creating
var levelPosition = Character.LevelPosition;
before I initiate the loop, but I kinda feel its ugly code to do this everytime I come across a similar situation. Maybe it -is- the way to go, but I want to make sure.
Is there a better or commonly accepted way to do this?
I'm using the XNA-Framework, which uses Vector2's.
From what I understand, you should avoid allocating lots of objects from the heap in XNA, because that causes bad performance. But since Vector2 is a struct, we're not allocating anything on the heap here, so that shouldn't be the problem here.
Now, if you have tight loop, like you do, in a performance-critical application, like a game, you will always have to think about performance, there is no going around that.
If we look at the code for LevelPosition, you call the getter for WorldPosition twice and probably some more getters. The getter for WorldPosition probably calls few other getters. (It's hard to say what exactly is going on without having the source, because getter call and field access look exactly the same.)
Call to a getter, which is actually just a call to a special method, is usually pretty fast and can be even faster if the compiler decides to use inlining. But all the calls add up together, especially if you call them in a loop.
The solution for this is some sort of caching. One option would be to make LevelPosition a field and devise a system to update it when necessary. This could work, but it could also actually hurt performance if you need to update it more often than you read it.
Another solution is, as you discovered, to cache the result in a local variable. If you know that this is correct, i.e. that the value of the property won't change during the execution of the loop, then that's awesome! You solved your performance problem and you did it with only a single line of code that's easily understandable to any programmer. What more do you want?
Let me restate that. You found a solution to your performance problem that:
works
is simple to implement
is easy to understand
I think such solution wold be very hard to beat.
Creating many objects in a loop may be an expensive operation (*). Maybe if would help to create the Vector2 in advance (for example when the coordinates change) and in the future just change the coordinates.
Example:
public class Character
{
private Vector2 m_worldPosition = new Vector2(0, 0);
private Vector2 m_levelPosition = new Vector2(0, 0);
....
public Vector2 WorldPosition
{
get
{
m_worldPosition.X = ...;
m_worldPosition.Y = ...;
return m_worldPosition;
}
}
public Vector2 LevelPosition
{
get
{
m_levelPosition.X = ...;
m_levelPosition.Y = ...;
return m_levelPosition;
}
}
}
EDIT
The same should be done for the LevelPosition property as well. See modified source code.
(*)
Tim Schmelter pointed me to this question with a detailed discussion about the impact of instantiating objects. I have rephrased my initial sentence that object creation is always expensive. While creating objects is not always an expensive operation, it may still slow down performance in certain cases.
You can make a private field to store the value and not compute it each time. You can make a method to update the private fields and subscribe for the Movement.Position changes in some way. This way the value will be computed only once when position changes.
Related
I'm currently working on a OO representation of a simplified chess game. Most of it is straightforward enough but one design decision I'm a little unsure about is the relationship between the chessBoard and pieces. The bottom line is I'm trying to figure out the best way to represent the chessboard / piece relationship so that I can easily and efficiently query "given a spot, is there a piece here" and "given a piece, what spot is it on"?
Currently, the Piece class stores both their own location (using a Spot class) and a reference to the Board class. The board class represents the board as a Dictionary<Spot, Piece> (the simplified game only has a few pieces so it felt unnecessary to store a mostly empty array of N by M spots like other examples I've seen) to track what spots on the board have what pieces on them. This is useful and seems intuitive to me since the piece can use the reference to the board when trying to move and ask "is there anyone at this spot?" and it can return the piece if any that is on a given spot. Similarly, in order to move the piece I need to know where it currently is and storing the location on the piece itself seems like a good OO approach.
The part where I'm running into some questions / trouble is how to keep those values in sync such that if I call (public method) Board.MovePiece() or (private setter) Piece.CurrentPosition = new spot() both Piece.CurrentPosition and the Board's Dictionary<Spot, Piece> are updated properly. Keeping everything as private as possible while making sure that calling a method on either the board or the piece while keeping the other class in sync is very tricky if not impossible. If C# had friend classes like C++ I could just make the Board a friend of the Piece then they could set each other's private vars no problem (I'm aware of internal which improves things but I don't think it prevents other code in the project from theoretically calling stuff it shouldn't). Right now my solution to this is a custom setter on the piece.CurrentPosition property so that every call to change it results in the correct call to public board members (which absolutely works) but I feel like I could do better. The biggest risk is the board methods are public and could be called outside the piece class and thus not update the piece location but I'm not a huge fan of the redundancy / slight complexity smell the code has currently.
Here's a simplified look at my code:
public class Board : IBoard
{
private uint _width;
private uint _height;
private Dictionary<Spot, Piece> _pieceLocations;
public Board(uint width, uint height)
{
_width = width;
_height = height;
_pieceLocations = new Dictionary<Spot, Piece>();
}
// heavily used by piece when determining legal moves, what pieces and free spaces are in range etc.
public Piece CheckSpot(Spot spot)
{
Piece piece;
if (_pieceLocations.TryGetValue(transformSpot(spot), out piece))
{
return piece;
}
return null;
}
/// remove instead of null to potentially optimize space a bit
public bool RemovePiece(Spot spot)
{
if (spot != null)
{
return _pieceLocations.Remove(transformSpot(spot));
}
return false;
}
/// This function will simply attempt to just move the piece to the specified destination.
/// It's up to the caller to make sure the move is a valid chess move, etc
public Spot MovePiece(Spot destination, Piece pieceToBeMoved)
{
// remove piece from current position
// note the need to have current position here
RemovePiece(pieceToBeMoved.CurrentPosition);
// attempt to place at and return new position
return PlacePiece(destination, pieceToBeMoved);
}
/// Simply places piece at specified destination if not occupied by another piece
private Spot PlacePiece(Spot destination, Piece pieceToPlace)
{
var transformedDestination = transformSpot(destination);
//business logic to check for stuff like a piece already at destination
_pieceLocations.Add(transformedDestination, pieceToPlace);
return transformedDestination;
}
Note transformSpot just makes sure coordinates are not out of bounds and "wraps them around" to be within board dimensions if need be.
public abstract class Piece : IPiece
{
protected IBoard _board;
public ColorType Color { get; protected set; }
private Spot _currentPosition;
public Piece(ColorType color, Spot currentPosition, IBoard board)
{
_board = board;
Color = color;
CurrentPosition = currentPosition ?? throw new ArgumentNullException(nameof(currentPosition), "When creating a piece you must specify a location");
}
public Spot CurrentPosition {
get { return _currentPosition; }
// I wanted to make sure that the piece's current position was always in sync with the board.
// Calling <Board> functinos here seemed like a reasonable approach.
protected set {
// if position is being set to null remove from board
if (value == null)
{
_board.RemovePiece(_currentPosition);
_currentPosition = null;
}
else
{
_currentPosition = _board.MovePiece(value, this);
}
}
}
public void Move()
{
// note that I now need the current position to figure out where I can go etc.
// insert logic to determine where we can move using chess rules etc.
var destination = new Spot(x,y);
// if spot is occupied remove piece
var occupyingPiece = _board.CheckSpot(destination);
if (occupyingPiece != null)
{
occupyingPiece.RemovePiece();
}
// call custom setter which in turn updates board to move piece from current spot to destination
CurrentPosition = destination;
}
public void RemovePiece()
{
// call custom setter which in turn updates board to remove piece
CurrentPosition = null;
}
And some super rough pseudo code for the main driver
List<Piece> whitePieces = generateWhitePieces();
List<Piece> blackPieces = generateBlackPieces();
while (gameActive)
{
//somehow determine which piece to move
var pieceToMove = whitePieces.PickPiece();
// could pass and store CurrentPosition at this level but if it's not stored on the piece or easily
// accessible from the board but feels slightly icky
pieceToMove.Move();
pieceToMove = blackPieces.PickPiece();
pieceToMove.Move();
// etc.
}
Again, main flaw on top of some possibly unneeded complexity seems to be that Board.MovePiece() needs to be public for Piece to call it but that means anyone can also call MovePiece() and move something on the board without updating the piece.
Possible solutions I have considered:
I'm totally overthinking this and this is a fairly reasonable approach.
having the piece own its own location feels right, just wish I had better access modifiers to protect sensitive values but allow friends to change them (I'm aware of internal but doesn't seem to solve my issues fully)
I could just remove currentPos and:
have the board class maintain a Dictionary<Piece, Spot>
This feels like simply shifting the issue and having board maintain two dictionaries of essentially the same info in different orders feels silly, but at least it tightly couples the data together and allows the board to be the "authority" on where everything is. Leaning towards this but have a feeling this could be optimized somehow with the right data structure
have the main driver / game class maintain a dictionary / tuple list of pieces and their current position and have the Piece.Move() pass back info on where the board tells them they are now.
Again this just feels like we're shifting the issue but even more so. On the other hand I can kinda see the rationale for the game to want to keep track of pieces but that still feels pretty anti OO and I'd probably prefer keeping this to the Board as described above.
In theory could also
Just make current position setter public so Board could change it directly and add some complex checks in both the Board functions and the Piece.CurrentPosition setter to make sure if one is changed so is the other.
Feels much worse and adds more complexities / risks than it solves in my opinion. If it weren't for this issue CurrentPosition should have a private setter.
Anyway would very much appreciate any feedback / insight!
EDIT: to be clear I'm assuming that the piece class owns its logic when it comes to how it can move, and uses the state of the board to determine what spaces it can move to. Something like Piece.DetermineMove(). Specifically the piece needs to know where it is and what pieces if any are on the spaces it can move to, pieces that threaten it, etc.
If that's a poor design I'm all ears but I have a hard time believing that a Piece class shouldn't own its own movement logic in an OOP design.
Opinions are going to be thick on this one, and there's really no absolutely correct answer. Each will have pros and cons, some of which you might not find out until much later on in development. That being said, here's mine. :)
What you really want to do is ensure that there is only one method to do any operation in your application, and only one place that biblical data is stored in the application (religious connotations aside, biblical meaning "true").
You can start with logical objects (in your domain) and attempt to place this one method into the object that it makes sense for. If it doesn't make sense, then you might need a different [mental] model.
You've started with Board, Piece and Spot and I like this so far. Since we want to keep the data for a location of a piece in one place, I think we want to do that at the board level, because it will make movement easier (a piece won't have to go "up" to the board and back "down" to another piece).
This means a Piece won't have a Spot property, only a type (knight, bishop, etc) and ColorType (white/black). The board will have the dictionary for the pieces with the Spot as the key (it's a good key - there can only be one piece on a square). This makes a lot of the logic easier. Moving a piece means taking it out of the dict and putting it back in at the destination:
// Move attempt method might look like this:
Piece thisPiece = ... ;
Spot old = (1, 1); // origin ..
Spot new = (2, 2); // .. destination
// do some validation
if (pieces.Contains(new) && pieces[new].color == thisPiece.color)
throw new SpotOccupiedByFriendlyPieceAndThisIsntACastleException();
// capture a piece
if (pieces.Contains(new) && pieces[new].color != thisPiece.color)
{
pieces.Remove(new);
}
pieces.Remove(old); // move the old piece from "old"...
pieces.Add(new, thisPiece); //... to "new"
By putting all the pieces in a Dictionary<Spot, Piece> at the board level, there's only one collection that holds the pieces-to-spots relationship (the board owns it), and the board can perform all the logic it needs to.
I have recently been trying out object pooling in unity to speed up the instantiation of several game objects at once.
However, since these are fairly complex objects I need to reset them when they go back in the pool.
I read that using ScriptableObject might be a good way to store the default values for an easy reset. But in order to do that I need to load a fresh ScriptableObject at runtime to store the actual values of the object.
So in pseudocode, i'd have a class with public MyScriptableData data and public MyScriptableData defaults
1) create new pooled object with default ScriptableObject data = defaults;;
2) do stuff that changes values of scriptable object during lifetime of object
3) deactivate, and then return pooled object to pool, resetting the scriptableObject to its default (data = defaults; again).
I have 3 main questions:
A) I'm not sure how to actually implement this. It seems to me, in step 2, the default values would be changed. Therefore resetting to defaults would do nothing. I thought about creating a new instance of my scriptable object using
data = ScriptableObject.CreateInstance<MyScriptableData>();
but then how would I copy in the default values from defaults, ensuring in never changing the defaults? I would like for the defaults to be editable in the unity editor as an asset.
B) If I use CreateInstance, will the performance be bad? The whole reason i'm doing this object pooling is to reduce the performance costs of object instantiation. I'd hate to reintroduce slow code by instantiating scriptable objects.
C) Is this approach alright? or is there a better way to reset objects before going back into the pool?
EDIT based on some answers: I already have a setup that has a long list of fields, and then stores the default values of theses fields in a dictionary. But I found every time I wanted to add/change/remove a field, I had to change code in several spots
ATTEMPTED SOLUTION (But wrong, see below): I created an extension method for ScriptableObject:
using UnityEngine;
using System.Reflection;
public static class ScriptableObjectExtension {
public static T ShallowCopy<T> (this T orig) where T : ScriptableObject {
T copiedObject = ScriptableObject.CreateInstance<T> ();
FieldInfo[] myObjectFields = orig.GetType ().GetFields (
BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Instance);
foreach (FieldInfo fi in myObjectFields) {
fi.SetValue (copiedObject, fi.GetValue (orig));
}
return copiedObject;
}
}
FINAL SOLUTION:
The above script worked to clone scriptable objects, however, it appears I was going down the wrong path with that solution.
Several people below pointed out that pooling isn't that important in unity for most applications. I had originally tried to put pooling in because my framerate according to the profiler was around 30-15 fps, and I thought pooling would help improve that.
Based on the comments I dug a bit deeper and found that there was a process called LogStringToConsole. I said to myself, could this be as simple as my Debug.Log statements slowing things down!? I deleted them and the huge spikes went away. Apparently Debug.Log causes huge performance problems. Now I'm well above 60fps. Because of this I have decided not to pool those objects (But I still use pooling on simpler objects in another scenario that are being spawned several times per second). This means I don't need to worry about scriptable objects here at all. I now have and instantiate that loads a prefab and an Init method to set things up, and the objects are destroyed when they are used up.
When I went back to using instantiate/destroy, I didn't notice a significant change in performance. Thanks for all the responses!
If you only ever need to reset the object's values whenever it deactivates, couldn't you simply use:
OnEnable()
{
default = data;
}
OnDisable()
{
data = default;
}
That would allow you to store / assign default data when it activates, and reset its data back to the default values when it deactivates.
How about when you created the object, in the Awake() or Start() save the default value that you want to have into bunch of variables or store it inside dictionary,
after that to reset the value just make a method maybe with name called Reset() and assign all the variables with the default values that you have stored before.
e.g.
// method 1
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
int speed = 10;
List<float> scores = new List<float>() {1.5f, 3.4f};
// method 2
SomeClass something = new SomeClass();
SomeClass defaultSomething = new SomeClass();
// and if the type can use const
string sth = "abc";
const string defaultSth = "abc";
void Awake()
{
defaultValues.Add("speed", speed);
defaultValues.Add("scores", new List<float>(scores)); // new list because it is reference type,
//and you dont want to store reference to the list because it will be edited during runtime
defaultSomething = something.Clone(); // edit, but you need to implement clone by yourself for that class or do something that will make other instance of the class with same value
}
void Reset()
{
speed = (int) defaultValues["speed"];
scores = (List<float>) defaultValues["scores"];
something = defaultSomething.Clone();
sth = defaultSth;
}
The downside is every instance will store their own default variables occupying memory, you could change them into static or const if you want later on
The other way is you make 1 instance which is used for just storing default value (dont modify this in runtime) and use C# reflection to copy all members value
C# Using Reflection to copy base class properties
Hope this helps
Note!!
From about 2014, as a rule you do not need to pool in Unity. Unity drastically improved performance so that, for typical game scenarios, it is not necessary.
Note that the OP eliminated the problem simply by removing their hand-pooling attempt.
In recent years Unity drastically improved their
garbage collection
memory handling
pool-like handling triggering heuristics
prefab and instantiation processes
Object creation in video games is completely trivial on modern hardware; typical scenarios like "bullets" only amount to a dozen or so items perhaps in a second; and you have a vast amount of luxury time in future quiet frames to do gc, etc. In the early days of Unity, you would have to write pooling by hand to achieve typical game multiple object requirements such as bullets. Thanks to Unity's efforts, this is now totally unnecessary for typical game scenarios (bullets, multiple NPCs etc).
You can pool if for some reason you want to, but it is totally unnecessary performance-wise, for typical video game needs. 2D or 3D.
I'm currently trying to learn the SOLID design principles along with behavior driven development, but am having quite the hard time getting my head around the Single Responsibility Principle. I've tried to find a good tutorial for c# that uses test driven development, but haven't been able to find anything worthwhile in that vein. Anyway, after spending a few days reading about it, I decided the best way to learn is by experience, so I started creating a small app using those principles best I can.
It's a simple bowling score calculator. I figured the best way to go about it was to work from the simplest part up, so I started at the ball (or throw) level. Right now I have created tests and an interface and class for dealing with ball(throw) scores, which makes sure they aren't invalid, ie. <10 or >0. After implementing this I realized that the ball class is basically just a nullable integer, so maybe I don't even need it... but for now it's there.
Following the ball, I decided the next logical thing to add was a frame interface and class. This is where I have gotten stuck. Here is where I'm at:
namespace BowlingCalc.Frames
{
public interface IFrame : BowlingCalc.Generic.ICheckValid
{
void AddThrow(int? score);
int? GetThrow(int throw_number);
}
}
namespace BowlingCalc.Frames
{
public class Frame : IFrame
{
private List<Balls.IBall> balls;
private Balls.IBall ball;
private int frame_number;
public Frame(Balls.IBall ball, int frame_number)
{
this.ball = ball;
this.frame_number = frame_number;
balls = new List<Balls.IBall>();
check_valid();
}
public void AddThrow(int? score)
{
var current_ball = ball;
current_ball.Score = score;
balls.Add(current_ball);
}
public int? GetThrow(int throw_number)
{
return balls[throw_number].Score;
}
public void check_valid()
{
if (frame_number < 0 || frame_number > 10)
{
throw (new Exception("InvalidFrameNumberException"));
}
}
}
}
The frame uses my previously implemented ball class through dependency injection to add ball scores to the frame. It also implements a way to return the score for any given ball in the frame.
What I want to do, and where I'm stuck, is I want to add a way to make sure the frame score is valid. (For the moment just the simple case of frames 1-9, where the combined score of both balls must be 10 or less. I will move on to the much more complicated frame 10 case later.)
The problem is I have no idea how to implement this in a SOLID way. I was thinking of adding the logic into the class, but that seems to go against the single responsibility principle. Then I thought to add it as a separate interface/class and then call that class on each frame when its score updates. I also thought of creating a separate interface, IValidator or something like that, and implementing that in the Frame class. Unfortunately, I have no idea which, if any, of these is the best/SOLID way of doing things.
So, what would be a good, SOLID way to implement a method that validates the score of a frame?
Note: Any critique of my code is very welcome. I am very excited learn to create better code, and happy to receive any help given.
When I think SRP, I tend to put the emphasis on the Responsibility aspect. The name of the class, in turn, should ideally describe its Responsibility. For some classes this is about what the class is supposed to 'be' (a Frame could be a good example if it lacks behavior and merely represents state), but when you have a behavioral responsibility, the name is about what the class is supposed to 'do'.
Computing scores by itself is a fairly small responsibility, so let's consider something slightly larger and more naturally decomposable. Here is one possible breakdown of a bowling game with simple responsibilities and with suitably paranoid encapsulation (we're all friends here, but nobody wants anybody to cheat by mistake.)
//My job is to keep score; I don't interpret the scores
public interface IScoreKeeper : IScoreReporter
{
void SetScore(int bowlerIndex, int frameIndex, int throwIndex, int score);
}
//My job is to report scores to those who want to know the score, but shouldn't be allowed to change it
public interface IScoreReporter
{
int? GetScore(int bowlerIndex, int frameIndex, int throwIndex);
}
//My job is to play the game when told that it's my turn
public interface IBowler
{
//I'm given access to the ScoreReporter at some point, so I can use that to strategize
//(more realisically, to either gloat or despair as applicable)
//Throw one ball in the lane, however I choose to do so
void Bowl(IBowlingLane lane);
}
//My job is to keep track of the pins and provide score feedback when they are knocked down
//I can be reset to allow bowling to continue
public interface IBowlingLane
{
int? GetLastScore();
void ResetLane();
}
//My job is to coordinate a game of bowling with multiple players
//I tell the Bowlers to Bowl, retrieve scores from the BowlingLane and keep
//the scores with the ScoreKeeper.
public interface IBowlingGameCoordinator
{
//In reality, I would probably have other service dependencies, like a way to send feedback to a monitor
//Basically anything that gets too complicated and can be encapsulated, I offload to some other service to deal with it
//I'm lazy, so all I want to do is tell everybody else what to do.
void PlayGame(IScoreKeeper gameScore, IEnumerable<IBowler> bowlers, IBowlingLane lane);
}
Note that if you wanted to use this model to simply compute scores (without playing a real game), you can have a stub Bowler (who does nothing) and a MockBowlingLane, who produces a series of score values. The BowlingGameCoordinator takes care of the current bowler, frame and throw, so the scores get accumulated.
What is the purpose of ICheckValid interface? Do you call check_valid elsewhere? In my opinion, since the frame_number seems to be in fact a read-only property of a Frame, why it would be wrong to verify its consistency right in the constructor without any additional interfaces for that? (Constructors are supposed to produce consistent objects and are thus free to validate incoming parameters however they like.)
However, rather than to ask how to properly validate this field, it might be better to ask why indeed you need the frame_number property in the Frame? It seems like this is an index of this item in some array - you may just use the index, why store it in the Frame? You may want to write some if/else logic later, such as:
if (frame_number == 10) {
// some rules
} else {
// other rules
}
However, this is unlikely a SOLID approach as you would probably end up writing this if/else statements in many parts of the Frame. Rather, you may create a base class FrameBase, define much of the logics there plus some abstract methods to be implemented in OrdinaryFrame and TenthFrame, where you would define different rules. This would enable you to avoid frame_number altogether -- you would just create nine OrdinaryFrames and one TenthFrame.
As for critique: your code seems to abstract balls and frames, but ignores 'throws', or 'rolls' for some reason. Consider a need to add trajectory information of each roll, you would need to change the IFrame interface, adding something like void SetThrowTrajectory(int throwNumber, IThrowTrajectory trajectory). However, if you abstract throws away in an e.g. IBallRoll, the trajectory-related functionality would easily fit there (as well as some Boolean computed properties, e.g. IsStrike, IsSpare).
I've written a helper class that takes a string in the constructor and provides a lot of Get properties to return various aspects of the string. Currently the only way to set the line is through the constructor and once it is set it cannot be changed. Since this class only has one internal variable (the string) I was wondering if I should keep it this way or should I allow the string to be set as well?
Some example code my help why I'm asking:
StreamReader stream = new StreamReader("ScannedFile.dat");
ScannerLine line = null;
int responses = 0;
while (!stream.EndOfStream)
{
line = new ScannerLine(stream.ReadLine());
if (line.IsValid && !line.IsKey && line.HasResponses)
responses++;
}
Above is a quick example of counting the number of valid responses in a given scanned file. Would it be more advantageous to code it like this instead?
StreamReader stream = new StreamReader("ScannedFile.dat");
ScannerLine line = new ScannerLine();
int responses = 0;
while (!stream.EndOfStream)
{
line.RawLine = stream.ReadLine();
if (line.IsValid && !line.IsKey && line.HasResponses)
responses++;
}
This code is used in the back end of a ASP.net web application and needs to be somewhat responsive. I am aware that this may be a case of premature optimization but I'm coding this for responsiveness on the client side and maintainability.
Thanks!
EDIT - I decided to include the constructor of the class as well (Yes, this is what it really is.) :
public class ScannerLine
{
private string line;
public ScannerLine(string line)
{
this.line = line;
}
/// <summary>Gets the date the exam was scanned.</summary>
public DateTime ScanDate
{
get
{
DateTime test = DateTime.MinValue;
DateTime.TryParseExact(line.Substring(12, 6).Trim(), "MMddyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out test);
return test;
}
}
/// <summary>Gets a value indicating whether to use raw scoring.</summary>
public bool UseRaw { get { return (line.Substring(112, 1) == "R" ? true : false); } }
/// <summary>Gets the raw points per question.</summary>
public float RawPoints
{
get
{
float test = float.MinValue;
float.TryParse(line.Substring(113, 4).Insert(2, "."), out test);
return test;
}
}
}
**EDIT 2 - ** I included some sample properties of the class to help clarify. As you can see, the class takes a fixed string from a scanner and simply makes it easier to break apart the line into more useful chunks. The file is a line delimiated file from a Scantron machine and the only way to parse it is a bunch of string.Substring calls and conversions.
I would definitely stick with the immutable version if you really need the class at all. Immutability makes it easier to reason about your code - if you store a reference to a ScannerLine, it's useful to know that it's not going to change. The performance is almost certain to be insignificant - the IO involved in reading the line is likely to be more significant than creating a new object. If you're really concerned about performance, should should benchmark/profile the code before you decide to make a design decision based on those performance worries.
However, if your state is just a string, are you really providing much benefit over just storing the strings directly and having appropriate methods to analyse them later? Does ScannerLine analyse the string and cache that analysis, or is it really just a bunch of parsing methods?
You're first approach is more clear. Performance wise you can gain something but I don't think is worth.
I would go with the second option. It's more efficient, and they're both equally easy to understand IMO. Plus, you probably have no way of knowing how many times those statements in the while loop are going to be called. So who knows? It could be a .01% performance gain, or a 50% performance gain (not likely, but maybe)!
Immutable classes have a lot of advantages. It makes sense for a simple value class like this to be immutable. The object creation time for classes is small for modern VMs. The way you have it is just fine.
I'd actually ditch the "instance" nature of the class entirely, and use it as a static class, not an instance as you are right now. Every property is entirely independent from each other, EXCEPT for the string used. If these properties were related to each other, and/or there were other "hidden" variables that were set up every time that the string was assigned (pre-processing the properties for example), then there'd be reasons to do it one way or the other with re-assignment, but from what you're doing there, I'd change it to be 100% static methods of the class.
If you insist on having the class be an instance, then for pure performance reasons I'd allow re-assignment of the string, as then the CLR isn't creating and destroying instances of the same class continually (except for the string itself obviously).
At the end of the day, IMO this is something you can really do any way you want since there are no other class instance variables. There may be style reasons to do one or the other, but it'd be hard to be "wrong" when solving that problem. If there were other variables in the class that were set upon construction, then this'd be a whole different issue, but right now, code for what you see as the most clear.
I'd go with your first option. There's no reason for the class to be mutable in your example. Keep it simple unless you actually have a need to make it mutable. If you're really that concerned with performance, then run some performance analysis tests and see what the differences are.
I often find myself writing a property that is evaluated lazily. Something like:
if (backingField == null)
backingField = SomeOperation();
return backingField;
It is not much code, but it does get repeated a lot if you have a lot of properties.
I am thinking about defining a class called LazyProperty:
public class LazyProperty<T>
{
private readonly Func<T> getter;
public LazyProperty(Func<T> getter)
{
this.getter = getter;
}
private bool loaded = false;
private T propertyValue;
public T Value
{
get
{
if (!loaded)
{
propertyValue = getter();
loaded = true;
}
return propertyValue;
}
}
public static implicit operator T(LazyProperty<T> rhs)
{
return rhs.Value;
}
}
This would enable me to initialize a field like this:
first = new LazyProperty<HeavyObject>(() => new HeavyObject { MyProperty = Value });
And then the body of the property could be reduced to:
public HeavyObject First { get { return first; } }
This would be used by most of the company, since it would go into a common class library shared by most of our products.
I cannot decide whether this is a good idea or not. I think the solutions has some pros, like:
Less code
Prettier code
On the downside, it would be harder to look at the code and determine exactly what happens - especially if a developer is not familiar with the LazyProperty class.
What do you think ? Is this a good idea or should I abandon it ?
Also, is the implicit operator a good idea, or would you prefer to use the Value property explicitly if you should be using this class ?
Opinions and suggestions are welcomed :-)
Just to be overly pedantic:
Your proposed solution to avoid repeating code:
private LazyProperty<HeavyObject> first =
new LazyProperty<HeavyObject>(() => new HeavyObject { MyProperty = Value });
public HeavyObject First {
get {
return first;
}
}
Is actually more characters than the code that you did not want to repeat:
private HeavyObject first;
public HeavyObject First {
get {
if (first == null) first = new HeavyObject { MyProperty = Value };
return first;
}
}
Apart from that, I think that the implicit cast made the code very hard to understand. I would not have guessed that a method that simply returns first, actually end up creating a HeavyObject. I would at least have dropped the implicit conversion and returned first.Value from the property.
Don't do it at all.
Generally using this kind of lazy initialized properties is a valid design choice in one case: when SomeOperation(); is an expensive operation (in terms of I/O, like when it requires a DB hit, or computationally) AND when you are certain you will often NOT need to access it.
That said, by default you should go for eager initialization, and when profiler says it's your bottleneck, then change it to lazy initialization.
If you feel urge to create that kind of abstraction, it's a smell.
Surely you'd at least want the LazyPropery<T> to be a value type, otherwise you've added memory and GC pressure for every "lazily-loaded" property in your system.
Also, what about multiple-threaded scenarios? Consider two threads requesting the property at the same time. Without locking, you could potentially create two instances of the underlying property. To avoid locking in the common case, you would want to do a double-checked lock.
I prefer the first code, because a) it is such a common pattern with properties that I immediately understand it, and b) the point you raised: that there is no hidden magic that you have to go look up to understand where and when the value is being obtained.
I like the idea in that it is much less code and more elegant, but I would be very worried about the fact that it becomes hard to look at it and tell what is going on. The only way I would consider it is to have a convention for variables set using the "lazy" way, and also to comment anywhere it is used. Now there isn't going to be a compiler or anything that will enforce those rules, so still YMMV.
In the end, for me, decisions like this boil down to who is going to be looking at it and the quality of those programmers. If you can trust your fellow developers to use it right and comment well then go for it, but if not, you are better off doing it in a easily understood and followed way. /my 2cents
I don't think worrying about a developer not understanding is a good argument against doing something like this...
If you think that then you couldn't do anything for the fear of someone not understanding what you did
You could write a tutorial or something in a central repository, we have here a wiki for these kind of notes
Overall, I think it's a good implementation idea (not wanting to start a debate whether lazyloading is a good idea or not)
What I do in this case is I create a Visual Studio code snippet. I think that's what you really should do.
For example, when I create ASP.NET controls, I often times have data that gets stored in the ViewState a lot, so I created a code snippet like this:
public Type Value
{
get
{
if(ViewState["key"] == null)
ViewState["key"] = someDefaultValue;
return (Type)ViewState["key"];
}
set{ ViewState["key"] = value; }
}
This way, the code can be easily created with only a little work (defining the type, the key, the name, and the default value). It's reusable, but you don't have the disadvantage of a complex piece of code that other developers might not understand.
I like your solution as it is very clever but I don't think you win much by using it. Lazy loading a private field in a public property is definitely a place where code can be duplicated. However this has always struck me as a pattern to use rather than code that needs to be refactored into a common place.
Your approach may become a concern in the future if you do any serialization. Also it is more confusing initially to understand what you are doing with the custom type.
Overall I applaud your attempt and appreciate its cleverness but would suggest that you revert to your original solution for the reasons stated above.
Personally, I don't think the LazyProperty class as is offers enough value to justify using it especially considering the drawbacks using it for value types has (as Kent mentioned). If you needed other functionality (like making it multithreaded), it might be justified as a ThreadSafeLazyProperty class.
Regarding the implicit property, I like the "Value" property better. It's a little more typing, but a lot more clear to me.
I think this is an interesting idea. First I would recommend that you hide the Lazy Property from the calling code, You don't want to leak into your domain model that it is lazy. Which your doing with the implicit operator so keep that.
I like how you can use this approach to handle and abstract away the details of locking for example. If you do that then I think there is value and merit. If you do add locking watch out for the double lock pattern it's very easy to get it wrong.